The Instant View Editor uses a three-column layout, so you really want to use it on a desktop screen that's wide enough. Sorry for the inconvenience.

Back to the main page »
Loaded on 13 Apr 2017. Reload Loading...

Original

Ctrl+S to Save Template is in contest. This is a sample template. Saving...

Rules

x
92
 
1
# This sample template explores how we can turn the Medium post on the left into a Telegram Instant View page as shown on the right — in several simple steps. If you're unsure what some of the elements used here do, check out the full documentation here: https://instantview.telegram.org/docs
2
3
# Place the version at the beginning of template. We recommend always using the latest available version of Instant View.
4
~version: "2.0"
5
6
### STEP 1: Define which pages get Instant View and which don't
7
8
# We only want to generate Instant View pages for articles. Other things, like lists of articles, profiles, the about section, etc. should be ignored.
9
# Conveniently, all article pages on Medium seem to have a <meta property="article:published_time"> tag.
10
# If this tag is not present, we'll assume that the page is not an article and does not require an Instant View page.
11
# This *condition* does the trick:
12
?exists: /html/head/meta[@property="article:published_time"]
13
14
### STEP 2: Define the essential elements
15
16
# The 'body' and 'title' *properties* are required for an Instant View page to work. 
17
# 'Subtitle' is optional for IV pages, but Medium posts can have subtitles, so it is essential that we reflect this in our template.
18
body:     //article
19
title:    $body//h1[1]
20
subtitle: $title/next-sibling::h2
21
22
### Now we'll set a cover image. It's also not required, but we need one if we want our Instant view page to look cool.
23
24
# Some Medium posts have a cover image in the header background, we can use that.
25
# First, let's assign the background node to the '$bg_section' *variable* for subsequent use.
26
$bg_section: $body//section[has-class("is-imageBackgrounded")]
27
# Call the @background_to_image *function* to convert the background image to an <img>
28
@background_to_image: $bg_section//div[has-class("section-backgroundImage")]
29
# Replace the //div tag with <figure> tags.
30
<figure>: $bg_section//div[has-class("section-background")]
31
# Set the figure as the value of the 'cover' *property*.
32
cover: $bg_section//figure
33
34
# If we didn't find a cover image, check a few other blocks that may contain it.
35
# Note that 'cover:' is a *property*, so by default it will not be overwritten once we've assigned a value for the first time. This means that each of the following rules will only be applied if we don't have a cover yet.
36
cover: $title/preceding::figure[.//img][not(has-class("is-partialWidth"))]
37
cover: $title/next-sibling::figure[.//img]
38
cover: $subtitle/next-sibling::figure[.//img]
39
cover: //figure[has-class("graf--layoutFillWidth")]
40
41
### Now to find an image for link previews. Links shared via Telegram will show an extended preview with a small picture in the chat. Let's try to find something for this image.
42
43
# If we've already got a cover, we'll use it for the link preview image too.
44
image_url: $cover/self::img/@src
45
image_url: $cover/self::figure//img/@src
46
47
# If we didn't find a cover, we'll take a picture from the meta tags. 
48
# Otherwise, the link preview will just have text in it, which is also OK.
49
image_url: //head/meta[@property="og:image"]/@content
50
51
### STEP 3: Further refinements
52
53
# Pullquote in Medium contains a 'strong' tag, but this shouldn't make the whole quote bold.
54
<span>:  //blockquote[has-class("graf--pullquote")]//strong
55
<aside>: //blockquote[has-class("graf--pullquote")]
56
57
# Now we'll inline embeds that are wrapped in additional frames using the '@inline' *function*.
58
@inline: $body//iframe[starts-with(@src, "/media/")]
59
60
# Medium shows preformatted blocks/blockquotes together if they are next to each other, we'll combine them using two breaks as a separator.
61
@combine(<br>,<br>): $body//pre/next-sibling::pre
62
@combine(<br>,<br>): $body//blockquote/next-sibling::blockquote
63
64
# Medium articles can contain embedded link previews, we'll show such previews as blockquotes.
65
$embed:           $body//div[has-class("graf--mixtapeEmbed")]
66
@remove:          $embed//a[has-class("mixtapeImage")]
67
$embed_link:      $embed/a
68
@detach:          $embed_link/strong
69
@before_el(./..): $embed_link/*
70
@wrap(<cite>):    $embed_link
71
<blockquote>:     $embed
72
73
## STEP 4: Cleanup
74
75
# Remove excessive nodes, we don't need them on the IV page.
76
@remove: //article/header
77
@remove: //article/footer
78
@remove: $body//a[contains(@href,"/adServer.bs")]
79
@remove: $body//p//*[has-class("graf-dropCap")]//img[has-class("graf-dropCapImage")]
80
@remove: $body//*[has-class("js-postMetaLockup")][.//a[@data-action="show-user-card"]]
81
82
# Remove the first divider, it's invisible on Medium pages anyway.
83
@remove: $body//section[1]//hr
84
@remove: $body//section[has-class("section--first")]//hr
85
@remove: $body//section[has-class("section--cover")]/following-sibling::*[1]/self::section//hr
86
@remove: $body//section[has-class("is-backgrounded")]/following-sibling::*[1]/self::section//hr
87
88
# Some pages use thin images as a divider. Telegram doesn't like thin images much, so we'll replace them with a simple divider.
89
@before(<hr>): $body//figure[.//img[number(@data-height) < 30][(number(@data-width) > number(@data-height) * 30)]]
90
@remove
91
92
### And that's it, we're done. Now the rules from the '..after' block will be applied and the Instant View page is ready. Feel free to click on the panel below to see what exactly is done in the '..after' section.
?true
+ ..after
xxxxxxxxxx
172
 
1
# We apply some additional rules to each Instant View template.
2
?exists: $body
3
4
#####   Widgets   #####
5
6
# Most widgets are iFrames that are compatible with the Instant View format and will work out of the box. But some popular widgets do not use iFrames and need a little extra work.
7
8
# We transform such widgets to an Instant-View-compatible format - into an iFrame with an 'src' attribute and use @before to insert them into the page. Then we use the @remove function to delete the unsupported widget (because the essential content from it is now present on the IV page).
9
10
# twitter-tweet
11
@before(<iframe>, \
12
  src, ".//a[starts-with(@href, \"https://twitter.com/\")][contains(@href, \"/status/\") or contains(@href, \"/statuses/\")]/@href", \
13
  class, "twitter-tweet" \
14
): $body//blockquote[has-class("twitter-tweet")]
15
@remove
16
17
# twitter-video
18
@before(<iframe>, \
19
  src, ".//a[starts-with(@href, \"https://twitter.com/\")][contains(@href, \"/status/\") or contains(@href, \"/statuses/\")]/@href", \
20
  class, "twitter-video" \
21
): $body//blockquote[has-class("twitter-video")]
22
@remove
23
24
# facebook post
25
$fb_post: $body//div[has-class("fb-post")][@data-href]
26
@urlencode: $fb_post/@data-href
27
@set_attr(data-src, "https://www.facebook.com/plugins/post.php?href=", @data-href, "&show_text=", @data-show-text, "&width=640"): $fb_post
28
@before(<iframe>, src, @data-src, class, "fb-post"): $fb_post
29
@remove
30
31
# facebook video
32
$fb_video: $body//div[has-class("fb-video")][@data-href]
33
@urlencode: $fb_video/@data-href
34
@set_attr(data-src, "https://www.facebook.com/plugins/video.php?href=", @data-href, "&show_text=", @data-show-text, "&width=640"): $fb_video
35
@before(<iframe>, src, @data-src, class, "fb-video"): $fb_video
36
@remove
37
38
# aparat
39
$aparat_video: $body//script[starts-with(@src, "https://www.aparat.com/embed/")]
40
@set_attr(data-hash, @src)
41
@match("^https://www.aparat.com/embed/([^?]+)", 1): $@
42
@set_attr(data-src, "https://www.aparat.com/video/video/embed/videohash/", @data-hash, "\\/vt/frame"): $aparat_video
43
@before(<iframe>, src, @data-src, class, "aparat"): $aparat_video
44
@remove
45
46
# instagram
47
@before(<iframe>, \
48
  src, ".//a[contains(@href, \"instagram.com/p/\")]/@href", \
49
  class, "instagram" \
50
): $body//blockquote[has-class("instagram-media")]
51
@remove
52
53
# github
54
<iframe>: $body//script[starts-with(@src,"https://gist.github.com/")]
55
56
# telegram
57
$tg_post: $body//*[self::script or self::blockquote][@data-telegram-post]
58
@set_attr(data-src, "https://t.me/", @data-telegram-post, "?embed=1"): $tg_post
59
@set_attr(data-src, @data-src, "&userpic=", @data-userpic): $tg_post[@data-userpic]
60
@set_attr(data-src, @data-src, "&single=1"): $tg_post[@data-single]
61
@before(<iframe>, src, @data-src, class, "telegram-post"): $tg_post
62
@remove
63
64
#####   Add Anchors   #####
65
# Instant View supports anchors. We can add them before each <a> tag that has a name attribute.
66
67
@before(<anchor>, name, @name): $body//a[@name]
68
69
#####   RTL   #####
70
# Some magic for better RTL support.
71
72
<bdi>: $body//span[@dir="ltr" or @dir="rtl" or @dir="auto"]
73
74
#####   Unsupported elements   #####
75
76
# We mark content that is not supported in the Instant View format using the @unsupported function. The Instant View bot will not generate an Instant View page if a page features matching elements. This is to make sure that users never get an Instant View page with incomplete information.
77
78
@unsupported: $body//embed
79
@unsupported: $body//object
80
@unsupported: $body//canvas
81
@unsupported: $body//table//table
82
83
# We also mark some popular widgets that are not supported yet but may get supported later.
84
85
# imgur
86
@unsupported: $body//blockquote[has-class("imgur-embed-pub")]
87
88
# reddit
89
@unsupported: $body//div[has-class("reddit-card")]
90
@unsupported: $body//div[has-class("reddit-embed")]
91
92
# playbuzz
93
@unsupported: $body//div[has-class("pb_feed")][@data-item]
94
95
# tiktok
96
@unsupported: $body//blockquote[has-class("tiktok-embed")]
97
98
#####   Cleanup   #####
99
# Remove all html comments, styles and scripts.
100
101
@remove: //comment()
102
@remove: //script
103
@remove: //style
104
105
#####   Simplifying   #####
106
# We use the @simplify function to process target nodes according to the Instant View format. The title, subtitle, kicker and cover already exist as separate elements on the Instant View page, so we no longer need them in the article's body.
107
108
@simplify: $title
109
@remove
110
@simplify: $subtitle
111
@remove
112
@simplify: $kicker
113
@remove
114
@simplify: $cover
115
@remove
116
117
# The body element should be an <article> for simplify to work correctly. This is the last step.
118
<article>: $body
119
@simplify
120
body!
121
122
#####   Meta information   #####
123
124
# Even if a page doesn't have an associated Instant View template, we can still get some meta information from it and use it for link previews. So we apply the following rules to all pages:
125
?true
126
127
$head: /html/head
128
$meta: $head/meta
129
130
# Meta tags may have various formats.
131
# We first bring them to the same format <meta name="key" content="value">.
132
@set_attr(name, @property): $meta[not(@name) and @property]
133
@set_attr(name, @itemprop): $meta[not(@name) and @itemprop]
134
@set_attr(content, @value): $meta[not(@content) and @value]
135
136
# An article can have several authors.
137
# We combine author names using a little magic.
138
@set_attr(name, "author"): $meta[@name="article:author"]
139
140
@append(<div>): $head
141
$authors_el:    $@
142
$authors:       $meta[@name="author"]
143
144
@append_to($authors_el): $authors
145
@remove: $authors[@content = ./following-sibling::meta[@name="author"]/@content]
146
$authors: $authors_el/meta[@name="author"]
147
@before(", ")
148
@remove: ($@)[1]
149
@before(@content): $authors
150
@remove
151
author: $authors_el
152
153
# Basic information can be usualy obtained from Open Graph or Twitter Cards metatags.
154
title: $meta[@name="twitter:title"]/@content[normalize-space()]
155
title: $meta[@name="og:title"]/@content[normalize-space()]
156
title: $head/title[normalize-space()]
157
158
description: $meta[@name="twitter:description"]/@content[normalize-space()]
159
description: $meta[@name="og:description"]/@content[normalize-space()]
160
description: $body/p[normalize-space()]
161
description: $meta[@name="description"]/@content[normalize-space()]
162
163
image_url: $meta[@name="twitter:image"]/@content[normalize-space()]
164
image_url: $meta[@name="og:image"]/@content[normalize-space()]
165
166
published_date: $meta[@name="article:published_time"]/@content
167
168
site_name: $meta[@name="og:site_name"]/@content
169
170
channel: $meta[@name="telegram:channel"]/@content
171
172
Applying template... Click 'Track Changes' to check

Preview

Link Preview