@data-visuals/create 7.1.1 → 7.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. package/package.json +1 -1
  2. package/templates/__common__/_package.json +4 -4
  3. package/templates/{graphic → __common__}/app/scripts/embeds/frames.js +0 -0
  4. package/templates/__common__/app/templates/macros/prose.html +2 -2
  5. package/templates/__common__/config/tasks/graphics-meta.js +92 -64
  6. package/templates/__common__/utils/deployment/deploy.js +0 -27
  7. package/templates/__common__/utils/deployment/update-log-sheet.js +67 -32
  8. package/templates/feature/app/index.html +73 -64
  9. package/templates/feature/app/scripts/components/Story.js +6 -2
  10. package/templates/feature/app/scripts/packs/graphic-embed.js +31 -0
  11. package/templates/feature/app/scripts/packs/main-embed.js +7 -0
  12. package/templates/feature/app/templates/{base-graphic.html → base-embed.html} +1 -3
  13. package/templates/feature/app/templates/base.html +2 -0
  14. package/templates/feature/app/templates/components/footer.html +3 -3
  15. package/templates/feature/app/templates/{graphic.html → embed.html} +6 -6
  16. package/templates/feature/app/templates/index-old.html +76 -0
  17. package/templates/feature/app/templates/macros/processors-queso.html +2 -2
  18. package/templates/feature/app/templates/macros/processors.html +7 -3
  19. package/templates/feature/project.config.js +2 -1
  20. package/templates/graphic/app/index.html +0 -15
  21. package/templates/graphic/app/templates/base.html +1 -3
  22. package/templates/graphic/app/templates/graphic.html +3 -0
  23. package/templates/graphic/project.config.js +3 -2
  24. package/templates/feature/app/index-queso.html +0 -81
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@data-visuals/create",
3
- "version": "7.1.1",
3
+ "version": "7.3.0",
4
4
  "description": "Create graphics and features the Data Visuals way.",
5
5
  "scripts": {
6
6
  "build:docs": "doctoc README.md --github",
@@ -17,7 +17,7 @@
17
17
  "workspace:push": "node ./utils/deployment/push-workspace.js"
18
18
  },
19
19
  "devDependencies": {
20
- "@babel/core": "^7.0.0",
20
+ "@babel/core": "^7.17.8",
21
21
  "@babel/plugin-proposal-class-properties": "^7.1.0",
22
22
  "@babel/plugin-syntax-dynamic-import": "^7.0.0",
23
23
  "@babel/plugin-transform-react-jsx": "^7.0.0",
@@ -28,7 +28,7 @@
28
28
  "ansi-colors": "^3.2.3",
29
29
  "archieml": "^0.4.1",
30
30
  "assets-webpack-plugin": "^6.1.2",
31
- "autoprefixer": "^9.0.2",
31
+ "autoprefixer": "^10.4.2",
32
32
  "aws-sdk": "^2.372.0",
33
33
  "babel-eslint": "^10.0.1",
34
34
  "babel-loader": "^8.0.0",
@@ -50,7 +50,7 @@
50
50
  "fast-glob": "^2.2.2",
51
51
  "fs-extra": "^7.0.0",
52
52
  "glob-watcher": "^5.0.3",
53
- "googleapis": "^83.0.0",
53
+ "googleapis": "^99.0.0",
54
54
  "html-minifier": "^3.5.21",
55
55
  "imagemin": "^7.0.0",
56
56
  "imagemin-gifsicle": "^7.0.0",
@@ -60,7 +60,7 @@
60
60
  "journalize": "^2.1.0",
61
61
  "mime-types": "^2.1.17",
62
62
  "nunjucks": "^3.0.1",
63
- "postcss": "^7.0.2",
63
+ "postcss": "^8.4.12",
64
64
  "postcss-flexbugs-fixes": "^4.1.0",
65
65
  "prettier": "^1.12.1",
66
66
  "puppeteer": "^5.5.0",
@@ -1,9 +1,9 @@
1
1
  {% import 'macros/processors.html' as processors %}
2
2
 
3
- {% macro prose(content, context, data) %}
3
+ {% macro prose(content, context, data, type) %}
4
4
  {% for item in content %}
5
5
  {% if processors[item.type] %}
6
- {{ processors[item.type](item.value, context, data) }}
6
+ {{ processors[item.type](item.value, context, data, type) }}
7
7
  {% else %}
8
8
  {{ processors['raw'](item.value, context, data) }}
9
9
  {% endif %}
@@ -138,30 +138,32 @@ const parseGraphic = async (
138
138
  : `${localURL}/${parentDir}/${name}.html`;
139
139
  await page.goto(url, { waitUntil: 'load' });
140
140
  const label = path.join(parentDir, `${name}.html`);
141
- const graphicPath = path.join(folder, parentDir);
142
- const graphicURL = ensureSlash(`https://${bucket}/${folder}/${parentDir}`);
141
+ const projectPath = path.join(folder, parentDir);
142
+ const projectURL = ensureSlash(`https://${bucket}/${folder}/${parentDir}`);
143
143
 
144
- // only consider HTML with data-graphic attribute present
144
+ // only consider HTML with data-graphic or data-feature attribute present
145
145
  try {
146
- await page.waitForSelector('[data-graphic]', {
146
+ await page.waitForSelector('[data-graphic], [data-feature]', {
147
147
  timeout: 5000,
148
148
  });
149
149
  } catch (e) {
150
150
  return false;
151
151
  }
152
152
 
153
- // get text from page
153
+ // get metadata
154
154
  const title = await getText({ key: 'title', page });
155
- const caption = await getText({ key: 'caption', page });
156
- const altText = await getText({ key: 'alt-text', page });
157
- const note = await getText({ key: 'note', page });
158
- const source = await getText({ key: 'source', page });
159
155
  const tags = await (await getText({ key: 'tags', page })).split(',');
160
156
  let credits = await getText({ key: 'credit', page });
161
157
 
162
- // ignore graphics with no title
158
+ // determine type of metadata
159
+ // assume the type is graphic unless data-feature is present
160
+ const type = (await page.$('[data-feature]')) ? 'feature' : 'graphic';
161
+
162
+ // ignore projects with no title
163
163
  if (title.length === 0) {
164
- logMessage(`${label} was skipped because no graphic was title set.`);
164
+ logMessage(
165
+ `${label} was skipped because no graphic or feature was title set.`
166
+ );
165
167
  return false;
166
168
  }
167
169
 
@@ -174,63 +176,89 @@ const parseGraphic = async (
174
176
  }
175
177
 
176
178
  // find all links
177
- const links = await page.$$eval('a', links =>
178
- links.map(link => {
179
- return {
180
- url: link.getAttribute('href'),
181
- text: link.textContent,
182
- isCTA:
183
- link.classList.contains('button') ||
184
- link.classList.contains('.c-button'),
185
- };
186
- })
187
- );
179
+ if (type == 'graphic') {
180
+ const caption = await getText({ key: 'caption', page });
181
+ const altText = await getText({ key: 'alt-text', page });
182
+ const note = await getText({ key: 'note', page });
183
+ const source = await getText({ key: 'source', page });
184
+
185
+ const links = await page.$$eval('a', links =>
186
+ links.map(link => {
187
+ return {
188
+ url: link.getAttribute('href'),
189
+ text: link.textContent,
190
+ isCTA:
191
+ link.classList.contains('button') ||
192
+ link.classList.contains('.c-button'),
193
+ };
194
+ })
195
+ );
188
196
 
189
- // take screenshots of page
190
- const { small, large } = await createPreviews({
191
- page,
192
- outputPath,
193
- });
197
+ // take screenshots of page
198
+ const { small, large } = await createPreviews({
199
+ page,
200
+ outputPath,
201
+ });
194
202
 
195
- // check if appleNewsIgnore is specified
196
- let showInAppleNews = true;
197
- if (parserOptions) {
198
- const { appleNewsIgnore } = parserOptions;
199
- showInAppleNews =
200
- !appleNewsIgnore.includes(parentDir) && !appleNewsIgnore.includes(label);
203
+ // check if appleNewsIgnore is specified
204
+ let showInAppleNews = true;
205
+ if (parserOptions) {
206
+ const { appleNewsIgnore } = parserOptions;
207
+ showInAppleNews =
208
+ !appleNewsIgnore.includes(parentDir) &&
209
+ !appleNewsIgnore.includes(label);
210
+ }
211
+
212
+ // all graphic data
213
+ return {
214
+ type,
215
+ title,
216
+ altText,
217
+ bucket,
218
+ projectPath,
219
+ projectURL,
220
+ caption,
221
+ createMonth,
222
+ createYear,
223
+ credits,
224
+ folder,
225
+ id,
226
+ lastBuildTime,
227
+ label,
228
+ links,
229
+ note,
230
+ previews: {
231
+ large: projectURL + large,
232
+ small: projectURL + small,
233
+ },
234
+ showInAppleNews,
235
+ source,
236
+ tags,
237
+ };
201
238
  }
202
239
 
203
- // all graphic data
204
- return {
205
- title,
206
- altText,
207
- bucket,
208
- graphicPath,
209
- graphicURL,
210
- caption,
211
- createMonth,
212
- createYear,
213
- credits,
214
- folder,
215
- id,
216
- lastBuildTime,
217
- label,
218
- links,
219
- note,
220
- previews: {
221
- large: graphicURL + large,
222
- small: graphicURL + small,
223
- },
224
- showInAppleNews,
225
- source,
226
- tags,
227
- };
240
+ if (type == 'feature') {
241
+ // all feature data
242
+ return {
243
+ type,
244
+ title,
245
+ bucket,
246
+ projectPath,
247
+ projectURL,
248
+ createMonth,
249
+ createYear,
250
+ credits,
251
+ folder,
252
+ id,
253
+ lastBuildTime,
254
+ label,
255
+ tags,
256
+ };
257
+ }
228
258
  };
229
259
 
230
260
  module.exports = async localURL => {
231
- const {
232
- parserOptions,
233
- } = config;
261
+ const { parserOptions } = config;
234
262
 
235
263
  // find all html pages in project
236
264
  const pages = await glob('**/*.html', {
@@ -277,7 +305,7 @@ module.exports = async localURL => {
277
305
  // output path
278
306
  const manifest = `${paths.appDist}/manifest.json`;
279
307
 
280
- // output JSON of all graphic data
308
+ // output JSON of all metadata
281
309
  try {
282
310
  await fs.outputJson(manifest, filtered);
283
311
  } catch (err) {
@@ -286,11 +314,11 @@ module.exports = async localURL => {
286
314
 
287
315
  // print output info in terminal
288
316
  if (filtered.length > 0) {
289
- logMessage(`Generated metadata for ${filtered.length} graphic(s)`, 'green');
317
+ logMessage(`Generated metadata for ${filtered.length} item(s)`, 'green');
290
318
  console.log(`✔ ${manifest}`);
291
319
  } else {
292
320
  logMessage(
293
- `No metadata generated. Could not find the data-graphic attribute in any HTML files.`,
321
+ `No metadata generated. Could not find the data-graphic or data-feature attribute in any HTML files.`,
294
322
  'red'
295
323
  );
296
324
  }
@@ -35,31 +35,4 @@ ${colors.blue.underline(mainPath)} (This has been copied to your clipboard.)
35
35
  Did you run ${colors.yellow(
36
36
  `npm run data:fetch`
37
37
  )} before deploying to get the latest data?`);
38
-
39
- if (projectType === 'feature') {
40
- console.log(`
41
- If you are deploying a feature, check Facebook/Twitter/other social platforms to make sure the
42
- share image shows up.`);
43
- }
44
-
45
- if (projectType === 'graphic') {
46
- console.log(`
47
- If you are deploying a graphic in a CMS story, there are a few steps. First,
48
- add this in the Content section of the Raw Plugin:
49
- ${colors.yellow(
50
- `<div class="dv201808-graphic dv201808-graphic--centered dv201808-graphic--centered-narrow" data-frame-src="${mainPath}" data-frame-sandbox="allow-scripts allow-same-origin allow-top-navigation-by-user-activation allow-top-navigation"></div>`
51
- )}`);
52
-
53
- console.log(`
54
- Next, add the style code snippet found in ${colors.yellow(
55
- 'app/styles/raw-plugin-styles.html'
56
- )} to the CSS content section of the Raw Plugin`);
57
-
58
- console.log(`
59
- Then, add this line to the JavaScript content section of the Raw Plugin:
60
- ${colors.yellow(
61
- '<script src="https://cdn.texastribune.org/lib/@newswire/frames@0.3.1/index.umd.js"></script>'
62
- )}
63
- ${colors.yellow('<script>newswireFrames.autoInitFrames();</script>')}`);
64
- }
65
38
  });
@@ -23,17 +23,17 @@ function getFileLink(files, type) {
23
23
  async function writeToSheet(
24
24
  sheets,
25
25
  spreadsheetId,
26
- projectType,
27
26
  projectID,
28
27
  projectURL,
28
+ metadataType,
29
29
  metadataInput
30
30
  ) {
31
31
  // get corresponding sheet
32
32
  let sheetName;
33
- if (projectType === 'graphic') {
33
+ if (metadataType === 'graphic') {
34
34
  sheetName = 'Embedded';
35
35
  }
36
- if (projectType === 'feature') {
36
+ if (metadataType === 'feature') {
37
37
  sheetName = 'Feature';
38
38
  }
39
39
 
@@ -96,6 +96,7 @@ let updateLogSheet = async (mainPath, config) => {
96
96
  const spreadsheetId = '1hCP5zGx8dNxk59gI9wBSFY2juJVM8OFCDY45VnNb2nI';
97
97
 
98
98
  // loop through metadata JSON
99
+ // if there is no metadata
99
100
  if (manifestJSON.length == 0) {
100
101
  let metadataInput = [
101
102
  [
@@ -119,42 +120,76 @@ let updateLogSheet = async (mainPath, config) => {
119
120
  await writeToSheet(
120
121
  sheets,
121
122
  spreadsheetId,
122
- config.projectType,
123
123
  config.id,
124
124
  mainPath,
125
+ config.projectType,
125
126
  metadataInput
126
127
  );
127
128
  } else {
128
129
  for (const metadata of manifestJSON) {
129
- let metadataInput = [
130
- [
130
+ let metadataInput;
131
+ if (metadata.type == 'graphic') {
132
+ metadataInput = [
133
+ [
134
+ metadata.id,
135
+ metadata.projectURL,
136
+ metadata.projectPath,
137
+ metadata.title,
138
+ metadata.caption,
139
+ metadata.altText,
140
+ `${metadata.createYear}-${metadata.createMonth}`,
141
+ metadata.lastBuildTime,
142
+ metadata.note,
143
+ metadata.source,
144
+ metadata.credits.join(', '),
145
+ metadata.tags.join(', '),
146
+ getFileLink(config.files, 'sheet'),
147
+ getFileLink(config.files, 'doc'),
148
+ metadata.previews.large,
149
+ metadata.previews.small,
150
+ ],
151
+ ];
152
+ }
153
+ if (metadata.type == 'feature') {
154
+ metadataInput = [
155
+ [
156
+ metadata.id,
157
+ metadata.projectURL,
158
+ metadata.projectPath,
159
+ metadata.title,
160
+ '',
161
+ '',
162
+ `${metadata.createYear}-${metadata.createMonth}`,
163
+ metadata.lastBuildTime,
164
+ '',
165
+ '',
166
+ metadata.credits.join(', '),
167
+ metadata.tags.join(', '),
168
+ getFileLink(config.files, 'sheet'),
169
+ getFileLink(config.files, 'doc'),
170
+ '',
171
+ '',
172
+ ],
173
+ ];
174
+ }
175
+
176
+ // find hostname
177
+ let urlObj = new URL(metadata.projectURL);
178
+
179
+ // do not write when capybara-test is the hostname
180
+ if (
181
+ urlObj.hostname == 'graphics.texastribune.org' ||
182
+ urlObj.hostname == 'apps.texastribune.org'
183
+ ) {
184
+ await writeToSheet(
185
+ sheets,
186
+ spreadsheetId,
131
187
  metadata.id,
132
- metadata.graphicURL,
133
- metadata.graphicPath,
134
- metadata.title,
135
- metadata.caption,
136
- metadata.altText,
137
- `${metadata.createYear}-${metadata.createMonth}`,
138
- metadata.lastBuildTime,
139
- metadata.note,
140
- metadata.source,
141
- metadata.credits.join(', '),
142
- metadata.tags.join(', '),
143
- getFileLink(config.files, 'sheet'),
144
- getFileLink(config.files, 'doc'),
145
- metadata.previews.large,
146
- metadata.previews.small,
147
- ],
148
- ];
149
-
150
- await writeToSheet(
151
- sheets,
152
- spreadsheetId,
153
- config.projectType,
154
- metadata.id,
155
- metadata.graphicURL,
156
- metadataInput
157
- );
188
+ metadata.projectURL,
189
+ metadata.type,
190
+ metadataInput
191
+ );
192
+ }
158
193
  }
159
194
  }
160
195
  }
@@ -1,77 +1,86 @@
1
1
  {% extends 'base.html' %}
2
- {% from 'macros/prose.html' import prose %}
3
- {% from 'macros/processors.html' import ad %}
2
+ {% from 'macros/prose-queso.html' import prose %}
3
+ {% from 'macros/processors-queso.html' import ad %}
4
4
 
5
5
  {% set jsPackName = 'main' %}
6
-
7
- {# data.text --> data/text.json #}
8
6
  {% set context = data.text %}
9
-
10
- {# data.data --> data/data.json #}
11
- {% set featureData = data.data %}
12
-
7
+ {% set graphicTags = context.guten_tags %}
13
8
  {% set authorComma = joiner() %}
14
9
 
15
- {% block content %}
16
- <div class="container">
17
- <header class="article-header text-center">
18
- <h1 class="article-title">{{ context.headline | widont or 'The only member-supported, digital-first, nonpartisan media organization' | widont }}</h1>
19
- <p class="article-byline">
20
- <span class="article-author">By {%- for author in context.authors or ['Super Cool Corgi', 'Friends'] -%}
21
- {% if not loop.last %}{{ authorComma() }}{% elif not loop.first %} and{% endif %} {{ author }}
22
- {%- endfor -%}
23
- </span>
24
- {% if context.update_date %}
25
- <span class="article-pub-update-date">
26
- <time datetime="{{ context.pub_date }}">Published: {{ apFormatDate(context.pub_date) }}</time>
27
- <time datetime="{{ context.update_date }}">Updated: {{ apFormatDate(context.update_date) | widont}} </time>
28
- </span>
29
- {% else %}
30
- <span class="article-pub-date">
31
- <time datetime="{{ context.pub_date }}">{{ apFormatDate(context.pub_date) }}</time>
32
- </span>
33
- {% endif %}
34
- </p>
35
- </header>
36
-
37
- {% include 'includes/shares.html' %}
38
- </div>
39
-
40
- <div class="container">
41
- <div class="intro-prose">
42
- {{ prose(context.prose, context, featureData) }}
43
- <p class="copy">Duis mattis orci a porta maximus. Pellentesque vel pellentesque augue, a condimentum nibh. Integer eget feugiat turpis, at vehicula metus. Vestibulum arcu dui, hendrerit sed purus sed, vulputate aliquam est. Duis quis metus sed odio commodo dapibus. Maecenas pulvinar elit sit amet lorem iaculis blandit. Aliquam vitae sollicitudin urna. Sed viverra tincidunt felis.</p>
44
-
45
- <h2 class="article-subheader copy">{{ 'A cool subhead here' | widont }}</h2>
46
-
47
- <p class="copy">Curabitur vestibulum sagittis diam, vitae pulvinar lorem accumsan ut. Mauris enim massa, vestibulum sed sollicitudin dapibus, ultrices eget ligula. Aenean tempor mi urna, eu porta tortor vehicula quis. Morbi hendrerit, eros nec interdum tempus, sem purus fringilla leo, ut iaculis urna tortor id diam. Duis laoreet maximus sapien, sed scelerisque sapien volutpat vel. Sed est lacus, sollicitudin nec euismod eu, placerat eget turpis. Quisque ultricies urna et mollis bibendum. Quisque tempus, elit ut faucibus hendrerit, augue enim faucibus massa, eu scelerisque dui eros at dolor. Sed rutrum, ipsum id convallis facilisis, justo ex rhoncus ex, in ultrices nisi augue vitae erat. Donec consequat ipsum ac nunc aliquam, eu porttitor quam viverra. Praesent ultrices, diam eget placerat sodales, magna magna porttitor urna, nec mollis ipsum odio at magna. Nulla ac consectetur turpis. Cras non ligula elementum, aliquet arcu ut, interdum nulla.</p>
48
-
49
- <p class="copy">Nam ornare ante eget erat egestas, eget pulvinar diam tincidunt. Nunc eget ligula ac mi facilisis tempus. Proin molestie nisl at urna pharetra commodo. Praesent tincidunt vestibulum purus, id dictum tortor aliquet ac. Pellentesque semper scelerisque justo ac luctus. Nullam malesuada urna a magna fringilla bibendum. Mauris quis hendrerit nisl, a lacinia lectus.</p>
50
- </div>
51
- </div>
52
-
53
- {# use 'none' as the value if the ad shoud not have a gray background #}
54
- {# do not put ads inside a container div #}
55
- {{ ad('gray') }}
56
-
57
- {# create another container for more prose if the text needs to be split by an ad #}
58
- <div class="container">
59
- <p class="copy">Curabitur vestibulum sagittis diam, vitae pulvinar lorem accumsan ut. Mauris enim massa, vestibulum sed sollicitudin dapibus, ultrices eget ligula. Aenean tempor mi urna, eu porta tortor vehicula quis. Morbi hendrerit, eros nec interdum tempus, sem purus fringilla leo, ut iaculis urna tortor id diam. Duis laoreet maximus sapien, sed scelerisque sapien volutpat vel. Sed est lacus, sollicitudin nec euismod eu, placerat eget turpis. Quisque ultricies urna et mollis bibendum. Quisque tempus, elit ut faucibus hendrerit, augue enim faucibus massa, eu scelerisque dui eros at dolor. Sed rutrum, ipsum id convallis facilisis, justo ex rhoncus ex, in ultrices nisi augue vitae erat. Donec consequat ipsum ac nunc aliquam, eu porttitor quam viverra. Praesent ultrices, diam eget placerat sodales, magna magna porttitor urna, nec mollis ipsum odio at magna. Nulla ac consectetur turpis. Cras non ligula elementum, aliquet arcu ut, interdum nulla.</p>
60
-
61
- <p class="copy">Nam ornare ante eget erat egestas, eget pulvinar diam tincidunt. Nunc eget ligula ac mi facilisis tempus. Proin molestie nisl at urna pharetra commodo. Praesent tincidunt vestibulum purus, id dictum tortor aliquet ac. Pellentesque semper scelerisque justo ac luctus. Nullam malesuada urna a magna fringilla bibendum. Mauris quis hendrerit nisl, a lacinia lectus.</p>
62
- </div>
63
-
64
- {{ ad('gray', 'footer') }}
65
-
66
- <div class="related-content" id="related-content-container"></div>
67
-
68
- <div id="ribbon-container"></div>
69
- {% endblock content %}
10
+ {% block google_fonts %}{# queso fonts found in CSS #}{% endblock google_fonts %}
11
+ {% block css_file %}
12
+ <link rel="stylesheet" href="{{ static('styles/min/main-queso.css') }}">
13
+ {% endblock css_file %}
14
+
15
+ {% block nav %}{% include 'components/navbar.html' %}{% endblock %}
16
+
17
+ {% block content_wrap %}
18
+ <main data-feature>
19
+ <article class="has-giant-btm-marg">
20
+ {% block content %}
21
+ <div class="has-page-padding has-giant-btm-marg">
22
+ <header class="t-align-center">
23
+ <h1 class="l-container l-container--m t-headline t-serif t-lh-s has-s-btm-marg" data-title>{{ context.headline | widont or 'The only member-supported, digital-first, nonpartisan media organization' | widont }}</h1>
24
+ <p class="t-byline t-links t-uppercase t-lsp-m t-size-xs has-text-gray-dark has-b-btm-marg">
25
+ <span class="t-byline__item">By <span data-credit>{%- for author in context.authors or ['Texas Tribune Staff'] -%}
26
+ {% if not loop.last %}{{ authorComma() }}{% elif not loop.first %} and{% endif %} <span class="l-display-ib">{{ author }}</span>
27
+ {%- endfor -%}</span>
28
+ </span>
29
+
30
+ {% if context.update_date %}
31
+ <span class="l-display-block">
32
+ <span class="t-byline__item">Published: <time datetime="{{ context.pub_date }}">{{ apFormatDate(context.pub_date) }}</time></span>
33
+ <span class="t-byline__item">Updated: <time datetime="{{ context.update_date }}">{{ apFormatDate(context.update_date) }}</time></span>
34
+ </span>
35
+ {% else %}
36
+ <span class="t-byline__item"><time datetime="{{ context.pub_date }}">{{ apFormatDate(context.pub_date) }}</time></span>
37
+ {% endif %}
38
+ </p>
39
+ </header>
40
+
41
+ {% include 'components/share.html' %}
42
+ </div>
43
+
44
+ <div class="t-serif t-links-underlined has-page-padding">
45
+ {{ prose(context.prose, context, data) }}
46
+
47
+ {# graphics are attached to this container #}
48
+ <div id="graphic"></div>
49
+
50
+ <p class="t-copy">Duis mattis orci a porta maximus. Pellentesque vel pellentesque augue, a condimentum nibh. Integer eget feugiat turpis, at vehicula metus. Vestibulum arcu dui, hendrerit sed purus sed, vulputate aliquam est. Duis quis metus sed odio commodo dapibus. Maecenas pulvinar elit sit amet lorem iaculis blandit. Aliquam vitae sollicitudin urna. Sed viverra tincidunt felis.</p>
51
+
52
+ <h2 class="t-copy t-copy--subheader">{{ 'A cool subhead here' | widont }}</h2>
53
+
54
+ <p class="t-copy">Curabitur vestibulum sagittis diam, vitae pulvinar lorem accumsan ut. Mauris enim massa, vestibulum sed sollicitudin dapibus, ultrices eget ligula. Aenean tempor mi urna, eu porta tortor vehicula quis. Morbi hendrerit, eros nec interdum tempus, sem purus fringilla leo, ut iaculis urna tortor id diam. Duis laoreet maximus sapien, sed scelerisque sapien volutpat vel. Sed est lacus, sollicitudin nec euismod eu, placerat eget turpis. Quisque ultricies urna et mollis bibendum. Quisque tempus, elit ut faucibus hendrerit, augue enim faucibus massa, eu scelerisque dui eros at dolor. Sed rutrum, ipsum id convallis facilisis, justo ex rhoncus ex, in ultrices nisi augue vitae erat. Donec consequat ipsum ac nunc aliquam, eu porttitor quam viverra. Praesent ultrices, diam eget placerat sodales, magna magna porttitor urna, nec mollis ipsum odio at magna. Nulla ac consectetur turpis. Cras non ligula elementum, aliquet arcu ut, interdum nulla.</p>
55
+
56
+ <p class="t-copy">Nam ornare ante eget erat egestas, eget pulvinar diam tincidunt. Nunc eget ligula ac mi facilisis tempus. Proin molestie nisl at urna pharetra commodo. Praesent tincidunt vestibulum purus, id dictum tortor aliquet ac. Pellentesque semper scelerisque justo ac luctus. Nullam malesuada urna a magna fringilla bibendum. Mauris quis hendrerit nisl, a lacinia lectus.</p>
57
+ </div>
58
+
59
+ {# use 'none' as the value if the ad should not have a gray background #}
60
+ {# do not put ads inside a container div #}
61
+ {{ ad('gray') }}
62
+
63
+ {# create another container for more prose if the text needs to be split by an ad #}
64
+ <div class="t-serif t-links-underlined has-page-padding">
65
+ <p class="t-copy">Curabitur vestibulum sagittis diam, vitae pulvinar lorem accumsan ut. Mauris enim massa, vestibulum sed sollicitudin dapibus, ultrices eget ligula. Aenean tempor mi urna, eu porta tortor vehicula quis. Morbi hendrerit, eros nec interdum tempus, sem purus fringilla leo, ut iaculis urna tortor id diam. Duis laoreet maximus sapien, sed scelerisque sapien volutpat vel. Sed est lacus, sollicitudin nec euismod eu, placerat eget turpis. Quisque ultricies urna et mollis bibendum. Quisque tempus, elit ut faucibus hendrerit, augue enim faucibus massa, eu scelerisque dui eros at dolor. Sed rutrum, ipsum id convallis facilisis, justo ex rhoncus ex, in ultrices nisi augue vitae erat. Donec consequat ipsum ac nunc aliquam, eu porttitor quam viverra. Praesent ultrices, diam eget placerat sodales, magna magna porttitor urna, nec mollis ipsum odio at magna. Nulla ac consectetur turpis. Cras non ligula elementum, aliquet arcu ut, interdum nulla.</p>
66
+
67
+ <p class="t-copy">Nam ornare ante eget erat egestas, eget pulvinar diam tincidunt. Nunc eget ligula ac mi facilisis tempus. Proin molestie nisl at urna pharetra commodo. Praesent tincidunt vestibulum purus, id dictum tortor aliquet ac. Pellentesque semper scelerisque justo ac luctus. Nullam malesuada urna a magna fringilla bibendum. Mauris quis hendrerit nisl, a lacinia lectus.</p>
68
+ </div>
69
+
70
+ {{ ad('gray', 'footer') }}
71
+ {% endblock content %}
72
+ </article>
73
+ </main>
74
+ <aside>
75
+ <div class="related-content l-container has-page-padding" id="related-content-container"></div>
76
+ <div id="ribbon-container"></div>
77
+ </aside>
78
+ {% endblock content_wrap %}
70
79
 
71
80
  {% block inline_data %}
72
81
  <script>
73
82
  window.ttData = {
74
- gutenTag: '{{ context.guten_tag or "subject-politics" }}'
83
+ gutenTag: '{{ context.related_tag or "subject-politics" }}'
75
84
  };
76
85
  </script>
77
86
  {% endblock inline_data %}
@@ -22,8 +22,12 @@ const Story = ({ headline, url, pub_date, sitewide_image }) => {
22
22
  </div>
23
23
  <div class="story-text c-story-block__text">
24
24
  <header class="story-header">
25
- <h4 class="story-headline t-serif t-size-b t-lh-s has-xxxs-btm-marg">{headline}</h4>
26
- <p class="story-byline t-byline t-links t-uppercase t-lsp-m t-size-xs has-text-gray-dark">{apdate(new Date(pub_date))}</p>
25
+ <h4 class="story-headline t-serif t-size-b t-lh-s has-xxxs-btm-marg">
26
+ {headline}
27
+ </h4>
28
+ <p class="story-byline t-byline t-links t-uppercase t-lsp-m t-size-xs has-text-gray-dark">
29
+ {apdate(new Date(pub_date))}
30
+ </p>
27
31
  </header>
28
32
  </div>
29
33
  </div>
@@ -0,0 +1,31 @@
1
+ /* eslint-disable no-unused-vars */
2
+ import * as d3 from 'd3';
3
+ import createBase from '../utils/d3-base';
4
+
5
+ // a reference to the default graphic container, change if needed
6
+ const container = d3.select('#graphic');
7
+
8
+ // a helper function to clear the container of its contents
9
+ const clearContainer = () => container.html('');
10
+
11
+ // a helper function to grab the container's width
12
+ const getFrameWidth = () => container.node().offsetWidth;
13
+
14
+ // import data by getting the window variable, OR by importing the filepath
15
+ // let data = window.DATA;
16
+ // import data from '../../../data/data.json';
17
+ // import data from 'Data/data.json';
18
+
19
+ /**
20
+ * This function is called to render a graphic, using d3 or a library of your choice.
21
+ *
22
+ * @return {void}
23
+ */
24
+ export default function renderGraphic() {
25
+ // pass the recalculated frameWidth to parts of your chart (like an axis) that change with resize!
26
+ clearContainer();
27
+ const frameWidth = getFrameWidth();
28
+ //
29
+ // rest of your code goes here
30
+ // use createBase() to create the base of an d3 chart
31
+ }
@@ -0,0 +1,7 @@
1
+ import { frameLoader } from '../embeds/frames';
2
+ import renderGraphic from './graphic-embed';
3
+
4
+ // included in index.html by default
5
+ // initiates frame so your graphic is wrapped in an AMP-compatible iframe
6
+ // renderGraphic() renders a coded graphic on load and on resize
7
+ frameLoader(renderGraphic);
@@ -25,9 +25,7 @@
25
25
  {% if graphicCredit %}
26
26
  <meta name="tt-graphic-credit" content="{{ graphicCredit }}" />
27
27
  {% endif %}
28
- {% if graphicTags %}
29
- <meta name="tt-graphic-tags" content="{{ graphicTags or 'subject-politics' }}" />
30
- {% endif %}
28
+ <meta name="tt-graphic-tags" content="{{ graphicTags or ['subject-politics'] }}" />
31
29
 
32
30
  <link rel="dns-prefetch" href="https://www.google-analytics.com">
33
31
  <link rel="dns-prefetch" href="https://fonts.googleapis.com">
@@ -4,6 +4,8 @@
4
4
  <title>{% if context.seo_headline %}{{ context.seo_headline + ' | ' }}{% elif context.headline %}{{ context.headline + ' | ' }}{% endif %}The Texas Tribune</title>
5
5
  {% include 'includes/metas.html' %}
6
6
 
7
+ <meta name="tt-graphic-tags" content="{{ graphicTags or ['subject-politics'] }}" />
8
+
7
9
  <link rel="dns-prefetch" href="https://www.google-analytics.com">
8
10
  <link rel="dns-prefetch" href="https://www.googletagmanager.com">
9
11
  {% block google_fonts %}
@@ -7,9 +7,9 @@
7
7
  <li class="footer-nav-item"><a class="footer-link" href="http://www.texastribune.org/about/">About Us</a></li>
8
8
  <li class="footer-nav-item"><a class="footer-link" href="http://www.texastribune.org/contact/">Contact Us</a></li>
9
9
  <li class="footer-nav-item"><a class="footer-link" href="http://www.texastribune.org/support-us/donors-and-members/">Who Funds Us?</a></li>
10
- <li class="footer-nav-item"><a class="footer-link" href="http://www.texastribune.org/terms-of-service/">Terms of Service</a></li>
11
- <li class="footer-nav-item"><a class="footer-link" href="http://www.texastribune.org/ethics/">Code of Ethics</a></li>
12
- <li class="footer-nav-item"><a class="footer-link" href="http://www.texastribune.org/privacy/">Privacy Policy</a></li>
10
+ <li class="footer-nav-item"><a class="footer-link" href="http://www.texastribune.org/about/terms-of-service/">Terms of Service</a></li>
11
+ <li class="footer-nav-item"><a class="footer-link" href="http://www.texastribune.org/about/ethics/">Code of Ethics</a></li>
12
+ <li class="footer-nav-item"><a class="footer-link" href="http://www.texastribune.org/about/privacy-policy/">Privacy Policy</a></li>
13
13
  <li class="footer-nav-item"><a class="footer-link footer-link-donate" href="https://support.texastribune.org/">Donate</a></li>
14
14
  </ul>
15
15
  </div>
@@ -1,9 +1,9 @@
1
1
  {# Template for any scripted graphics, i.e. D3 charts #}
2
- {% extends 'base-graphic.html' %}
2
+ {% extends 'base-embed.html' %}
3
3
  {% from 'macros/prose.html' import prose %}
4
4
 
5
5
  {# set pack that provides JS #}
6
- {% set jsPackName = 'main' %}
6
+ {% set jsPackName = 'main-embed' %}
7
7
 
8
8
  {# data.text --> data/text.json #}
9
9
  {% set context = data.text %}
@@ -23,16 +23,16 @@
23
23
  {# data-title is used to grab the title in the CMS #}
24
24
  <h1 class="graphic-title" data-title>{{ context.headline | widont }}</h1>
25
25
  {# data-caption is used to grab the caption in the CMS #}
26
- <span data-caption>{{ prose(context.graphic_prose, context, graphicData) }}</span>
26
+ <span data-caption>{{ prose(context.embed_prose, context, graphicData, 'embed') }}</span>
27
27
 
28
28
  {# container that JS is attached to #}
29
29
  <div id="graphic" class="graphic"></div>
30
30
 
31
31
  {# data-source, data-credit, and data-note are also used in the CMS #}
32
32
  <ul class="graphic-footer">
33
- {% if context.note %}<li data-note>Note: {{ context.note }}</li>{% endif %}
34
- {% if context.source %}<li data-source>Source: {{ context.source }}</li>{% endif %}
35
- {% if context.credit %}<li data-credit>Credit: {{ context.credit }}</li>{% endif %}
33
+ {% if context.embed_note %}<li data-note>Note: {{ context.embed_note }}</li>{% endif %}
34
+ {% if context.embed_source %}<li data-source>Source: {{ context.embed_source }}</li>{% endif %}
35
+ {% if context.embed_credit %}<li data-credit>Credit: {{ context.embed_credit }}</li>{% endif %}
36
36
  </ul>
37
37
  </div>
38
38
  {% endblock content %}
@@ -0,0 +1,76 @@
1
+ {% extends 'base.html' %}
2
+ {% from 'macros/prose.html' import prose %}
3
+ {% from 'macros/processors.html' import ad %}
4
+
5
+ {% set jsPackName = 'main' %}
6
+ {# data.text --> data/text.json #}
7
+ {% set context = data.text %}
8
+ {# data.data --> data/data.json #}
9
+ {% set featureData = data.data %}
10
+ {% set graphicTags = context.guten_tags %}
11
+ {% set authorComma = joiner() %}
12
+
13
+ {% block content %}
14
+ <div class="container" data-feature>
15
+ <header class="article-header text-center">
16
+ <h1 class="article-title" data-title>{{ context.headline | widont or 'The only member-supported, digital-first, nonpartisan media organization' | widont }}</h1>
17
+ <p class="article-byline">
18
+ <span class="article-author">By {%- for author in context.authors or ['Super Cool Corgi', 'Friends'] -%}
19
+ {% if not loop.last %}{{ authorComma() }}{% elif not loop.first %} and{% endif %} {{ author }}
20
+ {%- endfor -%}
21
+ </span>
22
+ {% if context.update_date %}
23
+ <span class="article-pub-update-date">
24
+ <time datetime="{{ context.pub_date }}">Published: {{ apFormatDate(context.pub_date) }}</time>
25
+ <time datetime="{{ context.update_date }}">Updated: {{ apFormatDate(context.update_date) | widont}} </time>
26
+ </span>
27
+ {% else %}
28
+ <span class="article-pub-date">
29
+ <time datetime="{{ context.pub_date }}">{{ apFormatDate(context.pub_date) }}</time>
30
+ </span>
31
+ {% endif %}
32
+ </p>
33
+ </header>
34
+
35
+ {% include 'includes/shares.html' %}
36
+ </div>
37
+
38
+ <div class="container">
39
+ <div class="intro-prose">
40
+ {{ prose(context.prose, context, featureData) }}
41
+
42
+ <p class="copy">Duis mattis orci a porta maximus. Pellentesque vel pellentesque augue, a condimentum nibh. Integer eget feugiat turpis, at vehicula metus. Vestibulum arcu dui, hendrerit sed purus sed, vulputate aliquam est. Duis quis metus sed odio commodo dapibus. Maecenas pulvinar elit sit amet lorem iaculis blandit. Aliquam vitae sollicitudin urna. Sed viverra tincidunt felis.</p>
43
+
44
+ <h2 class="article-subheader copy">{{ 'A cool subhead here' | widont }}</h2>
45
+
46
+ <p class="copy">Curabitur vestibulum sagittis diam, vitae pulvinar lorem accumsan ut. Mauris enim massa, vestibulum sed sollicitudin dapibus, ultrices eget ligula. Aenean tempor mi urna, eu porta tortor vehicula quis. Morbi hendrerit, eros nec interdum tempus, sem purus fringilla leo, ut iaculis urna tortor id diam. Duis laoreet maximus sapien, sed scelerisque sapien volutpat vel. Sed est lacus, sollicitudin nec euismod eu, placerat eget turpis. Quisque ultricies urna et mollis bibendum. Quisque tempus, elit ut faucibus hendrerit, augue enim faucibus massa, eu scelerisque dui eros at dolor. Sed rutrum, ipsum id convallis facilisis, justo ex rhoncus ex, in ultrices nisi augue vitae erat. Donec consequat ipsum ac nunc aliquam, eu porttitor quam viverra. Praesent ultrices, diam eget placerat sodales, magna magna porttitor urna, nec mollis ipsum odio at magna. Nulla ac consectetur turpis. Cras non ligula elementum, aliquet arcu ut, interdum nulla.</p>
47
+
48
+ <p class="copy">Nam ornare ante eget erat egestas, eget pulvinar diam tincidunt. Nunc eget ligula ac mi facilisis tempus. Proin molestie nisl at urna pharetra commodo. Praesent tincidunt vestibulum purus, id dictum tortor aliquet ac. Pellentesque semper scelerisque justo ac luctus. Nullam malesuada urna a magna fringilla bibendum. Mauris quis hendrerit nisl, a lacinia lectus.</p>
49
+ </div>
50
+ </div>
51
+
52
+ {# use 'none' as the value if the ad shoud not have a gray background #}
53
+ {# do not put ads inside a container div #}
54
+ {{ ad('gray') }}
55
+
56
+ {# create another container for more prose if the text needs to be split by an ad #}
57
+ <div class="container">
58
+ <p class="copy">Curabitur vestibulum sagittis diam, vitae pulvinar lorem accumsan ut. Mauris enim massa, vestibulum sed sollicitudin dapibus, ultrices eget ligula. Aenean tempor mi urna, eu porta tortor vehicula quis. Morbi hendrerit, eros nec interdum tempus, sem purus fringilla leo, ut iaculis urna tortor id diam. Duis laoreet maximus sapien, sed scelerisque sapien volutpat vel. Sed est lacus, sollicitudin nec euismod eu, placerat eget turpis. Quisque ultricies urna et mollis bibendum. Quisque tempus, elit ut faucibus hendrerit, augue enim faucibus massa, eu scelerisque dui eros at dolor. Sed rutrum, ipsum id convallis facilisis, justo ex rhoncus ex, in ultrices nisi augue vitae erat. Donec consequat ipsum ac nunc aliquam, eu porttitor quam viverra. Praesent ultrices, diam eget placerat sodales, magna magna porttitor urna, nec mollis ipsum odio at magna. Nulla ac consectetur turpis. Cras non ligula elementum, aliquet arcu ut, interdum nulla.</p>
59
+
60
+ <p class="copy">Nam ornare ante eget erat egestas, eget pulvinar diam tincidunt. Nunc eget ligula ac mi facilisis tempus. Proin molestie nisl at urna pharetra commodo. Praesent tincidunt vestibulum purus, id dictum tortor aliquet ac. Pellentesque semper scelerisque justo ac luctus. Nullam malesuada urna a magna fringilla bibendum. Mauris quis hendrerit nisl, a lacinia lectus.</p>
61
+ </div>
62
+
63
+ {{ ad('gray', 'footer') }}
64
+
65
+ <div class="related-content" id="related-content-container"></div>
66
+
67
+ <div id="ribbon-container"></div>
68
+ {% endblock content %}
69
+
70
+ {% block inline_data %}
71
+ <script>
72
+ window.ttData = {
73
+ gutenTag: '{{ context.related_tag or "subject-politics" }}'
74
+ };
75
+ </script>
76
+ {% endblock inline_data %}
@@ -9,7 +9,7 @@
9
9
  {% endmacro %}
10
10
 
11
11
  {% macro list(value) %}
12
- <ul>
12
+ <ul class="t-copy c-list">
13
13
  {% for item in value %}
14
14
  <li>{{ item }}</li>
15
15
  {% endfor %}
@@ -17,7 +17,7 @@
17
17
  {% endmacro %}
18
18
 
19
19
  {% macro subhead(value) %}
20
- <h2 class="t-subheader">{{ value | widont }}</h2>
20
+ <h2 class="t-copy t-copy--subheader">{{ value | widont }}</h2>
21
21
  {% endmacro %}
22
22
 
23
23
  {# set type to roof for roof ads, footer for footer ads #}
@@ -4,12 +4,16 @@
4
4
  {{ value | renderStringWithNunjucks(data) }}
5
5
  {% endmacro %}
6
6
 
7
- {% macro text(value, context, data) %}
8
- <p class="copy">{{ value | renderStringWithNunjucks(data) }}</p>
7
+ {% macro text(value, context, data, type) %}
8
+ {% if type == 'embed' %}
9
+ <p class="graphic-prose">{{ value | renderStringWithNunjucks(data) }}</p>
10
+ {% else %}
11
+ <p class="copy">{{ value | renderStringWithNunjucks(data) }}</p>
12
+ {% endif %}
9
13
  {% endmacro %}
10
14
 
11
15
  {% macro list(value) %}
12
- <ul>
16
+ <ul class="copy">
13
17
  {% for item in value %}
14
18
  <li>{{ item }}</li>
15
19
  {% endfor %}
@@ -34,7 +34,8 @@ module.exports = {
34
34
  projectName: '<<name>>',
35
35
  /**
36
36
  * The destination S3 bucket for a deploy.
37
- * YOU CAN CHANGE THIS.
37
+ * `capybara-test` is the test bucket.
38
+ * YOU CAN CHANGE THIS. Change to `apps.texastribune.org` when publishing.
38
39
  */
39
40
  bucket: 'capybara-test.texastribune.org',
40
41
  /**
@@ -2,21 +2,6 @@
2
2
  {% extends 'base.html' %}
3
3
  {% from 'macros/prose.html' import prose %}
4
4
 
5
- {# set pack that provides JS #}
6
- {% set jsPackName = 'main' %}
7
-
8
- {# data.text --> data/text.json #}
9
- {% set context = data.text %}
10
-
11
- {# data.data --> data/data.json #}
12
- {% set graphicData = data.data %}
13
-
14
- {# graphicAltText is used by the CMS for accessibility #}
15
- {% set graphicAltText = context.alttext %}
16
-
17
- {# graphics will be surfaced in the graphics plugin under these tags #}
18
- {% set graphicTags = context.guten_tags %}
19
-
20
5
  {% block content %}
21
6
  <div class="app">
22
7
  <h1 class="article-subheader">Welcome to The Texas Tribune's data visuals graphics kit!</h1>
@@ -25,9 +25,7 @@
25
25
  {% if graphicCredit %}
26
26
  <meta name="tt-graphic-credit" content="{{ graphicCredit }}" />
27
27
  {% endif %}
28
- {% if graphicTags %}
29
- <meta name="tt-graphic-tags" content="{{ graphicTags or 'subject-politics' }}" />
30
- {% endif %}
28
+ <meta name="tt-graphic-tags" content="{{ graphicTags or ['subject-politics'] }}" />
31
29
 
32
30
  <link rel="dns-prefetch" href="https://www.google-analytics.com">
33
31
  <link rel="dns-prefetch" href="https://fonts.googleapis.com">
@@ -14,6 +14,9 @@
14
14
  {# graphicAltText is used by the CMS for accessibility #}
15
15
  {% set graphicAltText = context.alttext %}
16
16
 
17
+ {# graphics will be surfaced in the graphics plugin under these tags #}
18
+ {% set graphicTags = context.guten_tags %}
19
+
17
20
  {% block content %}
18
21
  {# data-graphic signifies that this can be embedded in the CMS #}
19
22
  <div class="app" data-graphic>
@@ -34,9 +34,10 @@ module.exports = {
34
34
  projectName: '<<name>>',
35
35
  /**
36
36
  * The destination S3 bucket for a deploy.
37
- * YOU CAN CHANGE THIS.
37
+ * `capybara-test` is the test bucket.
38
+ * YOU CAN CHANGE THIS. Change to `graphics.texastribune.org` when publishing.
38
39
  */
39
- bucket: 'graphics.texastribune.org',
40
+ bucket: 'capybara-test.texastribune.org',
40
41
  /**
41
42
  * The folder (or "Key" in S3 lingo) to deploy the project into.
42
43
  * This is the slug in the project URL.
@@ -1,81 +0,0 @@
1
- {% extends 'base.html' %}
2
- {% from 'macros/prose-queso.html' import prose %}
3
- {% from 'macros/processors-queso.html' import ad %}
4
-
5
- {% set jsPackName = 'main' %}
6
- {% set context = data.text %}
7
- {% set authorComma = joiner() %}
8
-
9
- {% block google_fonts %}{# queso fonts found in CSS #}{% endblock google_fonts %}
10
- {% block css_file %}
11
- <link rel="stylesheet" href="{{ static('styles/min/main-queso.css') }}">
12
- {% endblock css_file %}
13
-
14
- {% block nav %}{% include 'components/navbar.html' %}{% endblock %}
15
-
16
- {% block content_wrap %}
17
- <main>
18
- <article class="has-giant-btm-marg">
19
- {% block content %}
20
- <div class="has-page-padding has-giant-btm-marg">
21
- <header class="t-align-center">
22
- <h1 class="l-container l-container--m t-headline t-serif t-lh-s has-s-btm-marg">{{ context.headline | widont or 'The only member-supported, digital-first, nonpartisan media organization' | widont }}</h1>
23
- <p class="t-byline t-links t-uppercase t-lsp-m t-size-xs has-text-gray-dark has-b-btm-marg">
24
- <span class="t-byline__item">By {%- for author in context.authors or ['Super Cool Corgi', 'Friends'] -%}
25
- {% if not loop.last %}{{ authorComma() }}{% elif not loop.first %} and{% endif %} <span class="l-display-ib">{{ author }}</span>
26
- {% endfor %}
27
- </span>
28
-
29
- {% if context.update_date %}
30
- <span class="l-display-block">
31
- <span class="t-byline__item">Published: <time datetime="{{ context.pub_date }}">{{ apFormatDate(context.pub_date) }}</time></span>
32
- <span class="t-byline__item">Updated: <time datetime="{{ context.update_date }}">{{ apFormatDate(context.update_date) }}</time></span>
33
- </span>
34
- {% else %}
35
- <span class="t-byline__item"><time datetime="{{ context.pub_date }}">{{ apFormatDate(context.pub_date) }}</time></span>
36
- {% endif %}
37
- </p>
38
- </header>
39
-
40
- {% include 'components/share.html' %}
41
- </div>
42
-
43
- <div class="t-serif t-links-underlined has-page-padding">
44
- {{ prose(context.prose, context, data) }}
45
- <p class="t-copy">Duis mattis orci a porta maximus. Pellentesque vel pellentesque augue, a condimentum nibh. Integer eget feugiat turpis, at vehicula metus. Vestibulum arcu dui, hendrerit sed purus sed, vulputate aliquam est. Duis quis metus sed odio commodo dapibus. Maecenas pulvinar elit sit amet lorem iaculis blandit. Aliquam vitae sollicitudin urna. Sed viverra tincidunt felis.</p>
46
-
47
- <h2 class="t-copy t-copy--subheader">{{ 'A cool subhead here' | widont }}</h2>
48
-
49
- <p class="t-copy">Curabitur vestibulum sagittis diam, vitae pulvinar lorem accumsan ut. Mauris enim massa, vestibulum sed sollicitudin dapibus, ultrices eget ligula. Aenean tempor mi urna, eu porta tortor vehicula quis. Morbi hendrerit, eros nec interdum tempus, sem purus fringilla leo, ut iaculis urna tortor id diam. Duis laoreet maximus sapien, sed scelerisque sapien volutpat vel. Sed est lacus, sollicitudin nec euismod eu, placerat eget turpis. Quisque ultricies urna et mollis bibendum. Quisque tempus, elit ut faucibus hendrerit, augue enim faucibus massa, eu scelerisque dui eros at dolor. Sed rutrum, ipsum id convallis facilisis, justo ex rhoncus ex, in ultrices nisi augue vitae erat. Donec consequat ipsum ac nunc aliquam, eu porttitor quam viverra. Praesent ultrices, diam eget placerat sodales, magna magna porttitor urna, nec mollis ipsum odio at magna. Nulla ac consectetur turpis. Cras non ligula elementum, aliquet arcu ut, interdum nulla.</p>
50
-
51
- <p class="t-copy">Nam ornare ante eget erat egestas, eget pulvinar diam tincidunt. Nunc eget ligula ac mi facilisis tempus. Proin molestie nisl at urna pharetra commodo. Praesent tincidunt vestibulum purus, id dictum tortor aliquet ac. Pellentesque semper scelerisque justo ac luctus. Nullam malesuada urna a magna fringilla bibendum. Mauris quis hendrerit nisl, a lacinia lectus.</p>
52
- </div>
53
-
54
- {# use 'none' as the value if the ad shoud not have a gray background #}
55
- {# do not put ads inside a container div #}
56
- {{ ad('gray') }}
57
-
58
- {# create another container for more prose if the text needs to be split by an ad #}
59
- <div class="t-serif t-links-underlined has-page-padding">
60
- <p class="t-copy">Curabitur vestibulum sagittis diam, vitae pulvinar lorem accumsan ut. Mauris enim massa, vestibulum sed sollicitudin dapibus, ultrices eget ligula. Aenean tempor mi urna, eu porta tortor vehicula quis. Morbi hendrerit, eros nec interdum tempus, sem purus fringilla leo, ut iaculis urna tortor id diam. Duis laoreet maximus sapien, sed scelerisque sapien volutpat vel. Sed est lacus, sollicitudin nec euismod eu, placerat eget turpis. Quisque ultricies urna et mollis bibendum. Quisque tempus, elit ut faucibus hendrerit, augue enim faucibus massa, eu scelerisque dui eros at dolor. Sed rutrum, ipsum id convallis facilisis, justo ex rhoncus ex, in ultrices nisi augue vitae erat. Donec consequat ipsum ac nunc aliquam, eu porttitor quam viverra. Praesent ultrices, diam eget placerat sodales, magna magna porttitor urna, nec mollis ipsum odio at magna. Nulla ac consectetur turpis. Cras non ligula elementum, aliquet arcu ut, interdum nulla.</p>
61
-
62
- <p class="t-copy">Nam ornare ante eget erat egestas, eget pulvinar diam tincidunt. Nunc eget ligula ac mi facilisis tempus. Proin molestie nisl at urna pharetra commodo. Praesent tincidunt vestibulum purus, id dictum tortor aliquet ac. Pellentesque semper scelerisque justo ac luctus. Nullam malesuada urna a magna fringilla bibendum. Mauris quis hendrerit nisl, a lacinia lectus.</p>
63
- </div>
64
-
65
- {{ ad('gray', 'footer') }}
66
- {% endblock content %}
67
- </article>
68
- </main>
69
- <aside>
70
- <div class="related-content l-container has-page-padding" id="related-content-container"></div>
71
- <div id="ribbon-container"></div>
72
- </aside>
73
- {% endblock content_wrap %}
74
-
75
- {% block inline_data %}
76
- <script>
77
- window.ttData = {
78
- gutenTag: '{{ context.guten_tag or "subject-politics" }}'
79
- };
80
- </script>
81
- {% endblock inline_data %}