sfc-utils 1.2.5
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.
- package/README.md +47 -0
- package/blueconic.js +58 -0
- package/brands.js +180 -0
- package/copy/c2p_sheet.js +186 -0
- package/copy/docs.js +177 -0
- package/copy/googleauth.js +153 -0
- package/copy/sheets.js +151 -0
- package/fonts/albany.less +45 -0
- package/fonts/default.less +50 -0
- package/fonts/houston.less +51 -0
- package/fonts/sfc.less +57 -0
- package/footer.js +615 -0
- package/index.js +254 -0
- package/nav.js +247 -0
- package/package.json +14 -0
- package/settings.js +86 -0
- package/specialnav.js +128 -0
- package/topper.js +825 -0
package/index.js
ADDED
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
|
|
2
|
+
// Check to see if this should serve the app version of the project
|
|
3
|
+
let appCheck = function(){
|
|
4
|
+
// Save current env
|
|
5
|
+
const env = process.env.GATSBY_DEPLOY_ENV
|
|
6
|
+
|
|
7
|
+
let appVersion = false
|
|
8
|
+
// If env reports app, then it's app by default
|
|
9
|
+
if (env === 'app'){
|
|
10
|
+
appVersion = true
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// If we can access window, check to see if we're dealing with app version
|
|
14
|
+
if (typeof window !== "undefined"){
|
|
15
|
+
// Any link with ?fromRichie=1 will have paywall disabled
|
|
16
|
+
// Native in-app webviews will have a custom user agent, so check that too
|
|
17
|
+
if (window.location.href.indexOf('fromRichie=1') > -1 || navigator.userAgent.indexOf(' Richie/') > -1) {
|
|
18
|
+
appVersion = true
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return appVersion
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Blend the HDN var with whatever is already present on the page
|
|
26
|
+
// Returns a string for injection into the head of the page
|
|
27
|
+
let blendHDN = function(meta){
|
|
28
|
+
|
|
29
|
+
if (!meta.PROJECT){
|
|
30
|
+
// If we don't have a properly formatted meta var coming in, this is a legacy template and needs settings pulled
|
|
31
|
+
let url_add = meta.url_add || ""
|
|
32
|
+
meta = getSettings()
|
|
33
|
+
meta.URL_ADD = url_add
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Set vars with the new object
|
|
37
|
+
let {
|
|
38
|
+
PAYWALL_SETTING,
|
|
39
|
+
URL_ADD,
|
|
40
|
+
MAIN_DOMAIN,
|
|
41
|
+
PROJECT: {
|
|
42
|
+
AUTHORS,
|
|
43
|
+
ANALYTICS_CREDIT,
|
|
44
|
+
TITLE,
|
|
45
|
+
HEARST_CATEGORY,
|
|
46
|
+
KEY_SUBJECTS,
|
|
47
|
+
SUBFOLDER,
|
|
48
|
+
OPT_SLASH,
|
|
49
|
+
SLUG,
|
|
50
|
+
MARKET_KEY,
|
|
51
|
+
ISO_PUBDATE,
|
|
52
|
+
ISO_MODDATE,
|
|
53
|
+
CANONICAL_URL
|
|
54
|
+
},
|
|
55
|
+
} = meta
|
|
56
|
+
BASE_DOMAIN = MAIN_DOMAIN
|
|
57
|
+
if (MARKET_KEY === "CT"){
|
|
58
|
+
BASE_DOMAIN = "ctinsider.com"
|
|
59
|
+
}
|
|
60
|
+
let siteDomain
|
|
61
|
+
if(CANONICAL_URL){
|
|
62
|
+
siteDomain = CANONICAL_URL.match('^(.+?).com')[0]
|
|
63
|
+
}
|
|
64
|
+
else{
|
|
65
|
+
siteDomain = MAIN_DOMAIN
|
|
66
|
+
}
|
|
67
|
+
// Check if we need a slash
|
|
68
|
+
let slash = OPT_SLASH
|
|
69
|
+
|
|
70
|
+
// Add the canonical here unless it's sent in
|
|
71
|
+
if (!CANONICAL_URL){
|
|
72
|
+
CANONICAL_URL = `${BASE_DOMAIN}/${SUBFOLDER}${slash}${SLUG}`
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// If canonical has a slash at the end, remove it
|
|
76
|
+
if (CANONICAL_URL.slice(-1) === "/"){
|
|
77
|
+
CANONICAL_URL = CANONICAL_URL.slice(0, -1)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Add the url add here unless it's sent in
|
|
81
|
+
if (!URL_ADD){
|
|
82
|
+
URL_ADD = ""
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// If url add does not end with a /, add it
|
|
86
|
+
if (URL_ADD && URL_ADD.slice(-1) !== "/"){
|
|
87
|
+
URL_ADD += "/"
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Get dates from env
|
|
91
|
+
let pubdate = ""
|
|
92
|
+
if (ISO_PUBDATE){
|
|
93
|
+
pubdate = ISO_PUBDATE.toString().split('T')[0] + " 00:00:00"
|
|
94
|
+
}
|
|
95
|
+
let moddate = ""
|
|
96
|
+
if (ISO_MODDATE){
|
|
97
|
+
moddate = ISO_MODDATE.toString().split('T')[0] + " 00:00:00"
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Setting up vars
|
|
101
|
+
let HDN = {}
|
|
102
|
+
HDN.dataLayer = {}
|
|
103
|
+
HDN.dataLayer.content = {}
|
|
104
|
+
HDN.dataLayer.href = {}
|
|
105
|
+
HDN.dataLayer.source = {}
|
|
106
|
+
HDN.dataLayer.sharing = {}
|
|
107
|
+
HDN.dataLayer.presentation = {}
|
|
108
|
+
HDN.dataLayer.paywall = {}
|
|
109
|
+
|
|
110
|
+
// HDN.dataLayer object for content and href data
|
|
111
|
+
HDN.dataLayer.content.title = TITLE
|
|
112
|
+
HDN.dataLayer.content.subtitle = ''
|
|
113
|
+
HDN.dataLayer.content.objectId = `${SUBFOLDER}${slash}${SLUG}/${URL_ADD}`
|
|
114
|
+
HDN.dataLayer.content.objectType = 'project'
|
|
115
|
+
|
|
116
|
+
// Check if we have more than one HEARST_CATEGORY, split on commas
|
|
117
|
+
var categories = HEARST_CATEGORY.split(',').map(item=>item.trim())
|
|
118
|
+
HDN.dataLayer.content.sectionPath = categories
|
|
119
|
+
|
|
120
|
+
var key_subjects = KEY_SUBJECTS ? KEY_SUBJECTS.split(',').map(item=>item.trim()) : []
|
|
121
|
+
HDN.dataLayer.content.keySubjects = key_subjects
|
|
122
|
+
HDN.dataLayer.content.pubDate = pubdate
|
|
123
|
+
HDN.dataLayer.content.lastModifiedDate = moddate
|
|
124
|
+
HDN.dataLayer.content.wordCount = ''
|
|
125
|
+
HDN.dataLayer.content.keywords = []
|
|
126
|
+
HDN.dataLayer.content.keyPersons = []
|
|
127
|
+
HDN.dataLayer.content.keyOrganizations = []
|
|
128
|
+
HDN.dataLayer.content.keyConcepts = []
|
|
129
|
+
HDN.dataLayer.content.keyCategories = []
|
|
130
|
+
HDN.dataLayer.content.keyPlaces = []
|
|
131
|
+
HDN.dataLayer.content.keyNlpPerson = []
|
|
132
|
+
HDN.dataLayer.content.keyNlpLocation = []
|
|
133
|
+
HDN.dataLayer.content.keyNlpOrganization = []
|
|
134
|
+
HDN.dataLayer.content.keyNlpEvent = []
|
|
135
|
+
HDN.dataLayer.content.keyNlpWorkOfArt = []
|
|
136
|
+
HDN.dataLayer.content.keyNlpConsumerGood = []
|
|
137
|
+
HDN.dataLayer.content.keyNlpOther = []
|
|
138
|
+
HDN.dataLayer.content.keyNlpUnknown = []
|
|
139
|
+
|
|
140
|
+
// HDN.dataLayer object for source information
|
|
141
|
+
HDN.dataLayer.source.authorName = ''
|
|
142
|
+
|
|
143
|
+
HDN.dataLayer.source.authorTitle = '';
|
|
144
|
+
HDN.dataLayer.source.originalSourceSite = '';
|
|
145
|
+
HDN.dataLayer.source.publishingSite = '';
|
|
146
|
+
HDN.dataLayer.source.sourceSite = '';
|
|
147
|
+
switch(MARKET_KEY){
|
|
148
|
+
case "SFC":
|
|
149
|
+
HDN.dataLayer.source.authorTitle = 'San Francisco Chronicle Staff';
|
|
150
|
+
HDN.dataLayer.source.originalSourceSite = 'SF';
|
|
151
|
+
HDN.dataLayer.source.publishingSite = 'premiumsfgate';
|
|
152
|
+
HDN.dataLayer.source.sourceSite = 'sfgate';
|
|
153
|
+
break;
|
|
154
|
+
case "Houston":
|
|
155
|
+
HDN.dataLayer.source.authorTitle = 'Houston Chronicle Staff';
|
|
156
|
+
HDN.dataLayer.source.originalSourceSite = 'HC';
|
|
157
|
+
break;
|
|
158
|
+
case "SanAntonio":
|
|
159
|
+
HDN.dataLayer.source.authorTitle = 'Express News Staff';
|
|
160
|
+
HDN.dataLayer.source.originalSourceSite = 'EN';
|
|
161
|
+
break;
|
|
162
|
+
case "Albany":
|
|
163
|
+
HDN.dataLayer.source.authorTitle = 'Times Union Staff';
|
|
164
|
+
HDN.dataLayer.source.originalSourceSite = 'TU';
|
|
165
|
+
break;
|
|
166
|
+
case "CT":
|
|
167
|
+
HDN.dataLayer.source.authorTitle = 'Connecticut Digital Staff';
|
|
168
|
+
HDN.dataLayer.source.originalSourceSite = 'CT';
|
|
169
|
+
break;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// HDN.dataLayer object for sharing information
|
|
173
|
+
HDN.dataLayer.sharing.openGraphUrl =`${siteDomain}/${SUBFOLDER}${slash}${SLUG}/${URL_ADD}`
|
|
174
|
+
HDN.dataLayer.sharing.openGraphType = 'article'
|
|
175
|
+
|
|
176
|
+
// More page settings
|
|
177
|
+
HDN.dataLayer.href.pageUrl = `${siteDomain}/${SUBFOLDER}${slash}${SLUG}/${URL_ADD}`
|
|
178
|
+
HDN.dataLayer.href.canonicalUrl = `${CANONICAL_URL}/${URL_ADD}`
|
|
179
|
+
|
|
180
|
+
// HDN.dataLayer object for presentation information
|
|
181
|
+
HDN.dataLayer.presentation.hasSlideshow = ''
|
|
182
|
+
HDN.dataLayer.presentation.hasSlideshowListView = ''
|
|
183
|
+
HDN.dataLayer.presentation.hasVideo = ''
|
|
184
|
+
HDN.dataLayer.presentation.hasInteractive = ''
|
|
185
|
+
|
|
186
|
+
// HDN.dataLayer object for paywall information
|
|
187
|
+
HDN.dataLayer.paywall.premiumStatus = 'isPremium'
|
|
188
|
+
HDN.dataLayer.paywall.premiumEndDate = ''
|
|
189
|
+
HDN.dataLayer.paywall.policy = PAYWALL_SETTING
|
|
190
|
+
|
|
191
|
+
// Special site var
|
|
192
|
+
HDN.dataLayer.site = {
|
|
193
|
+
domain: siteDomain.replace("https://www.",""),
|
|
194
|
+
domainRoot: siteDomain.replace("https://www.","").replace(".com",""),
|
|
195
|
+
subDomain: 'www',
|
|
196
|
+
name: HDN.dataLayer.source.publishingSite,
|
|
197
|
+
property: HDN.dataLayer.source.originalSourceSite,
|
|
198
|
+
siteId: '35',
|
|
199
|
+
siteUrl: siteDomain,
|
|
200
|
+
timeZone: 'Pacific',
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Create author for analytics here
|
|
204
|
+
let authorString = ""
|
|
205
|
+
if (ANALYTICS_CREDIT !== ''){
|
|
206
|
+
authorString = ANALYTICS_CREDIT
|
|
207
|
+
} else if (AUTHORS){
|
|
208
|
+
// If one wasn't specified, use the one in the config
|
|
209
|
+
AUTHORS.forEach((author, index) => {
|
|
210
|
+
// Add author to string
|
|
211
|
+
authorString += author.AUTHOR_NAME
|
|
212
|
+
// Add comma if we're not done
|
|
213
|
+
if (index < (AUTHORS.length - 1)){
|
|
214
|
+
authorString += ", "
|
|
215
|
+
}
|
|
216
|
+
})
|
|
217
|
+
}
|
|
218
|
+
// If we didn't get any author, sub in default
|
|
219
|
+
if (authorString === ""){
|
|
220
|
+
authorString = HDN.dataLayer.source.authorTitle
|
|
221
|
+
}
|
|
222
|
+
HDN.dataLayer.source.authorName = authorString
|
|
223
|
+
|
|
224
|
+
let appVer = appCheck()
|
|
225
|
+
if (appVer){
|
|
226
|
+
HDN.dataLayer.paywall.mode = "edbDisabled"
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
let stringHDN = `
|
|
230
|
+
var HDN = HDN || {};
|
|
231
|
+
HDN.dataLayer = HDN.dataLayer || {};
|
|
232
|
+
HDN.dataLayer.content = Object.assign(HDN.dataLayer.content || {}, ${JSON.stringify(HDN.dataLayer.content)});
|
|
233
|
+
HDN.dataLayer.source = Object.assign(HDN.dataLayer.source || {}, ${JSON.stringify(HDN.dataLayer.source)});
|
|
234
|
+
HDN.dataLayer.sharing = Object.assign(HDN.dataLayer.sharing || {}, ${JSON.stringify(HDN.dataLayer.sharing)});
|
|
235
|
+
HDN.dataLayer.href = Object.assign(HDN.dataLayer.href || {}, ${JSON.stringify(HDN.dataLayer.href)});
|
|
236
|
+
HDN.dataLayer.paywall = Object.assign(HDN.dataLayer.paywall || {}, ${JSON.stringify(HDN.dataLayer.paywall)});
|
|
237
|
+
HDN.dataLayer.site = Object.assign(HDN.dataLayer.site || {}, ${JSON.stringify(HDN.dataLayer.site)});
|
|
238
|
+
`
|
|
239
|
+
|
|
240
|
+
return {
|
|
241
|
+
stringHDN: stringHDN
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Grab neighbor files
|
|
246
|
+
let { getBrands } = require('./brands')
|
|
247
|
+
let { getSettings } = require('./settings')
|
|
248
|
+
let { getNav } = require('./nav')
|
|
249
|
+
let { getSpecialNav } = require('./specialnav')
|
|
250
|
+
let { getFooter } = require('./footer')
|
|
251
|
+
let { getTopper } = require('./topper')
|
|
252
|
+
let { getBlueconic } = require('./blueconic')
|
|
253
|
+
|
|
254
|
+
module.exports = { appCheck, blendHDN, getSettings, getBrands, getNav, getSpecialNav, getFooter, getTopper, getBlueconic }
|
package/nav.js
ADDED
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
let { getBrands } = require("./brands");
|
|
2
|
+
|
|
3
|
+
// Handle nav for various markets and include nav options for other links
|
|
4
|
+
let getNav = function (
|
|
5
|
+
meta,
|
|
6
|
+
urlAdd,
|
|
7
|
+
forceColor,
|
|
8
|
+
navLink,
|
|
9
|
+
navArray,
|
|
10
|
+
subInstead
|
|
11
|
+
) {
|
|
12
|
+
// If we aren't passing meta in, we have to call getSettings here
|
|
13
|
+
if (!meta) {
|
|
14
|
+
let { getSettings } = require("./settings");
|
|
15
|
+
meta = getSettings();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// If a link object was not provided, make one
|
|
19
|
+
if (!navLink) {
|
|
20
|
+
navLink = {
|
|
21
|
+
url: "#___gatsby",
|
|
22
|
+
text: "Special Report",
|
|
23
|
+
target: "_self",
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// If a navArray was provided, create the subnav
|
|
28
|
+
let subnav = "";
|
|
29
|
+
let dropdownIcon = "";
|
|
30
|
+
if (navArray && navArray.length > 0) {
|
|
31
|
+
subnav = `<ul id="subnav">`;
|
|
32
|
+
for (let i = 0; i < navArray.length; i++) {
|
|
33
|
+
subnav += `<li><a class="active" href="${navArray[i].url}" target="${navArray[i].target}"><span class="arrow-bullet">▶</span> ${navArray[i].text}</a></li>`;
|
|
34
|
+
}
|
|
35
|
+
subnav += `</ul>`;
|
|
36
|
+
// Add a dropdown icon
|
|
37
|
+
dropdownIcon = `<div class="dropdown-icon">▾</div>`;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Extension to URL if passed in
|
|
41
|
+
if (!urlAdd) {
|
|
42
|
+
urlAdd = "";
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
let {
|
|
46
|
+
attributes: { marketPrefix, invert, subscribeLink },
|
|
47
|
+
} = getBrands(meta.PROJECT.MARKET_KEY);
|
|
48
|
+
// Handle various CT domains
|
|
49
|
+
if (typeof window !== "undefined") {
|
|
50
|
+
switch (window.location.origin) {
|
|
51
|
+
case "https://www.ctpost.com":
|
|
52
|
+
marketPrefix = "ct";
|
|
53
|
+
break;
|
|
54
|
+
case "https://www.nhregister.com":
|
|
55
|
+
marketPrefix = "nh";
|
|
56
|
+
break;
|
|
57
|
+
case "https://www.greenwichtime.com":
|
|
58
|
+
marketPrefix = "gt";
|
|
59
|
+
break;
|
|
60
|
+
case "https://www.stamfordadvocate.com":
|
|
61
|
+
marketPrefix = "st";
|
|
62
|
+
break;
|
|
63
|
+
case "https://www.thehour.com":
|
|
64
|
+
marketPrefix = "th";
|
|
65
|
+
break;
|
|
66
|
+
case "https://www.newstimes.com":
|
|
67
|
+
marketPrefix = "nt";
|
|
68
|
+
break;
|
|
69
|
+
case "https://www.middletownpress.com":
|
|
70
|
+
marketPrefix = "mp";
|
|
71
|
+
break;
|
|
72
|
+
case "https://www.ctinsider.com":
|
|
73
|
+
marketPrefix = "in";
|
|
74
|
+
break;
|
|
75
|
+
|
|
76
|
+
case "https://www.beaumontenterprise.com":
|
|
77
|
+
marketPrefix = "texcom/beau";
|
|
78
|
+
break;
|
|
79
|
+
case "https://www.lmtonline.com":
|
|
80
|
+
marketPrefix = "texcom/laredo";
|
|
81
|
+
break;
|
|
82
|
+
case "https://www.mrt.com":
|
|
83
|
+
marketPrefix = "texcom/mrt";
|
|
84
|
+
break;
|
|
85
|
+
case "https://www.myplainview.com":
|
|
86
|
+
marketPrefix = "texcom/plain";
|
|
87
|
+
break;
|
|
88
|
+
|
|
89
|
+
case "https://www.bigrapidsnews.com":
|
|
90
|
+
marketPrefix = "midcom/big";
|
|
91
|
+
break;
|
|
92
|
+
case "https://www.manisteenews.com":
|
|
93
|
+
marketPrefix = "midcom/mani";
|
|
94
|
+
break;
|
|
95
|
+
case "https://www.ourmidland.com":
|
|
96
|
+
marketPrefix = "midcom/mid";
|
|
97
|
+
break;
|
|
98
|
+
case "https://www.michigansthumb.com":
|
|
99
|
+
marketPrefix = "midcom/huron";
|
|
100
|
+
break;
|
|
101
|
+
case "https://www.recordpatriot.com":
|
|
102
|
+
marketPrefix = "midcom/benzie";
|
|
103
|
+
break;
|
|
104
|
+
case "https://www.theheraldreview.com":
|
|
105
|
+
marketPrefix = "midcom/hr";
|
|
106
|
+
break;
|
|
107
|
+
case "https://www.lakecountystar.com":
|
|
108
|
+
marketPrefix = "midcom/lc";
|
|
109
|
+
break;
|
|
110
|
+
case "https://www.thetelegraph.com":
|
|
111
|
+
marketPrefix = "midcom/alton";
|
|
112
|
+
break;
|
|
113
|
+
case "https://www.theintelligencer.com":
|
|
114
|
+
marketPrefix = "midcom/ed";
|
|
115
|
+
break;
|
|
116
|
+
case "https://www.myjournalcourier.com":
|
|
117
|
+
marketPrefix = "midcom/jv";
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Default is white text on black nav (SFC style)
|
|
123
|
+
let invertClass = "";
|
|
124
|
+
let color = "white";
|
|
125
|
+
// If inverted, do black on white nav
|
|
126
|
+
// Only change things if color isn't forced to white
|
|
127
|
+
if (invert || forceColor === "white") {
|
|
128
|
+
invertClass = "invert";
|
|
129
|
+
color = "black";
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
let subfolder = "";
|
|
133
|
+
if (meta.PROJECT.SUBFOLDER) {
|
|
134
|
+
subfolder = meta.PROJECT.SUBFOLDER + "/";
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
let rightBlock = `
|
|
138
|
+
<div class="topper-nav-social">
|
|
139
|
+
<a
|
|
140
|
+
id="topper-nav-mail-icon"
|
|
141
|
+
title="Share via email"
|
|
142
|
+
href="mailto:?subject=${meta.PROJECT.TITLE}&body=${meta.PROJECT.DESCRIPTION}%0A%0A${meta.MAIN_DOMAIN}%2F${subfolder}${meta.PROJECT.SLUG}%2F${urlAdd}">
|
|
143
|
+
<svg
|
|
144
|
+
width="24"
|
|
145
|
+
height="24"
|
|
146
|
+
viewBox="0 0 24 24"
|
|
147
|
+
fill="none"
|
|
148
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
149
|
+
>
|
|
150
|
+
<path
|
|
151
|
+
fill-rule="evenodd"
|
|
152
|
+
clip-rule="evenodd"
|
|
153
|
+
d="M3.00977 5.83789C3.00977 5.28561 3.45748 4.83789 4.00977 4.83789H20C20.5523 4.83789 21 5.28561 21 5.83789V17.1621C21 18.2667 20.1046 19.1621 19 19.1621H5C3.89543 19.1621 3 18.2667 3 17.1621V6.16211C3 6.11449 3.00333 6.06765 3.00977 6.0218V5.83789ZM5 8.06165V17.1621H19V8.06199L14.1215 12.9405C12.9499 14.1121 11.0504 14.1121 9.87885 12.9405L5 8.06165ZM6.57232 6.80554H17.428L12.7073 11.5263C12.3168 11.9168 11.6836 11.9168 11.2931 11.5263L6.57232 6.80554Z"
|
|
154
|
+
fill="currentColor"
|
|
155
|
+
/>
|
|
156
|
+
</svg>
|
|
157
|
+
</a>
|
|
158
|
+
</div>
|
|
159
|
+
<div class="topper-nav-social">
|
|
160
|
+
<a
|
|
161
|
+
id="topper-nav-facebook-icon"
|
|
162
|
+
title="Share on Facebook"
|
|
163
|
+
href="https://www.facebook.com/sharer/sharer.php?u=${meta.MAIN_DOMAIN}%2F${subfolder}${meta.PROJECT.SLUG}%2F${urlAdd}"
|
|
164
|
+
target="_blank"
|
|
165
|
+
rel="noopener noreferrer"
|
|
166
|
+
>
|
|
167
|
+
<svg
|
|
168
|
+
width="24"
|
|
169
|
+
height="24"
|
|
170
|
+
viewBox="0 0 24 24"
|
|
171
|
+
fill="none"
|
|
172
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
173
|
+
>
|
|
174
|
+
<path
|
|
175
|
+
d="M9.19795 21.5H13.198V13.4901H16.8021L17.198 9.50977H13.198V7.5C13.198 6.94772 13.6457 6.5 14.198 6.5H17.198V2.5H14.198C11.4365 2.5 9.19795 4.73858 9.19795 7.5V9.50977H7.19795L6.80206 13.4901H9.19795V21.5Z"
|
|
176
|
+
fill="currentColor"
|
|
177
|
+
/>
|
|
178
|
+
</svg>
|
|
179
|
+
</a>
|
|
180
|
+
</div>
|
|
181
|
+
|
|
182
|
+
<div class="topper-nav-social">
|
|
183
|
+
<a target="_blank" rel="noopener noreferrer" id="twitter-icon" title="Share on Twitter" href="https://twitter.com/intent/tweet?url=${meta.MAIN_DOMAIN}%2F${subfolder}${meta.PROJECT.SLUG}%2F${urlAdd}&text=${meta.PROJECT.TWITTER_TEXT}">
|
|
184
|
+
<svg
|
|
185
|
+
width="24"
|
|
186
|
+
height="24"
|
|
187
|
+
viewBox="0 0 248 204"
|
|
188
|
+
fill="none"
|
|
189
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
190
|
+
>
|
|
191
|
+
<path
|
|
192
|
+
data-name="Twitter Logo"
|
|
193
|
+
fill="currentColor"
|
|
194
|
+
d="M222 51.29c.15 2.16.15 4.34.15 6.52 0 66.74-50.8 143.69-143.69 143.69A142.91 142.91 0 0 1 1 178.82a102.72 102.72 0 0 0 12 .72 101.29 101.29 0 0 0 62.72-21.66 50.53 50.53 0 0 1-47.18-35.07 50.35 50.35 0 0 0 22.8-.86 50.53 50.53 0 0 1-40.52-49.5v-.64a50.25 50.25 0 0 0 22.92 6.32 50.55 50.55 0 0 1-15.6-67.42 143.38 143.38 0 0 0 104.08 52.77 50.55 50.55 0 0 1 86.06-46.06 101.19 101.19 0 0 0 32.06-12.26 50.66 50.66 0 0 1-22.2 27.93 100.89 100.89 0 0 0 29-7.94A102.84 102.84 0 0 1 222 51.29z"
|
|
195
|
+
/>
|
|
196
|
+
</svg>
|
|
197
|
+
</a>
|
|
198
|
+
</div>
|
|
199
|
+
`;
|
|
200
|
+
|
|
201
|
+
if (subInstead) {
|
|
202
|
+
rightBlock = `
|
|
203
|
+
<a class="sub-box" href="${subscribeLink}" target="_blank">
|
|
204
|
+
<div>Subscribe</div>
|
|
205
|
+
</a>
|
|
206
|
+
`;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
let navHTML = `<nav class="topper-nav-container ${invertClass}">
|
|
210
|
+
<div class="topper-nav-left">
|
|
211
|
+
<a
|
|
212
|
+
href="/"
|
|
213
|
+
target="_blank"
|
|
214
|
+
rel="noopener noreferrer"
|
|
215
|
+
>
|
|
216
|
+
<div>
|
|
217
|
+
<img
|
|
218
|
+
class="topper-nav-desk-logo"
|
|
219
|
+
alt="Logo"
|
|
220
|
+
src="https://files.sfchronicle.com/static-assets/logos/${marketPrefix}-${color}.png"
|
|
221
|
+
></img>
|
|
222
|
+
<img
|
|
223
|
+
class="topper-nav-mobile-logo"
|
|
224
|
+
alt="Logo"
|
|
225
|
+
src="https://files.sfchronicle.com/static-assets/logos/${marketPrefix}-square-${color}.png"
|
|
226
|
+
></img>
|
|
227
|
+
</div>
|
|
228
|
+
</a>
|
|
229
|
+
<a
|
|
230
|
+
class="topper-nav-title"
|
|
231
|
+
id="nav-title"
|
|
232
|
+
href="${navLink.url}"
|
|
233
|
+
target="${navLink.target || "_blank"}"
|
|
234
|
+
>
|
|
235
|
+
${navLink.text}${dropdownIcon}
|
|
236
|
+
</a>
|
|
237
|
+
</div>
|
|
238
|
+
<div class="topper-nav-right">
|
|
239
|
+
${rightBlock}
|
|
240
|
+
</div>
|
|
241
|
+
${subnav}
|
|
242
|
+
</nav>`;
|
|
243
|
+
|
|
244
|
+
return navHTML;
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
module.exports = { getNav };
|
package/package.json
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "sfc-utils",
|
|
3
|
+
"version": "1.2.5",
|
|
4
|
+
"author": "ewagstaff <evanjwagstaff@gmail.com>",
|
|
5
|
+
"dependencies": {
|
|
6
|
+
"archieml": "^0.4.2",
|
|
7
|
+
"async": "^3.2.1",
|
|
8
|
+
"googleapis": "59.0.0",
|
|
9
|
+
"html-entities": "1.3.1",
|
|
10
|
+
"htmlparser2": "4.1.0",
|
|
11
|
+
"opn": "^6.0.0",
|
|
12
|
+
"write": "^2.0.0"
|
|
13
|
+
}
|
|
14
|
+
}
|
package/settings.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
|
|
2
|
+
/* Handle the data/processing for the Hearst analytics and paywall configuration */
|
|
3
|
+
let projectConfig;
|
|
4
|
+
try {
|
|
5
|
+
projectConfig = require("../../project-config.json")
|
|
6
|
+
} catch (err){
|
|
7
|
+
try {
|
|
8
|
+
projectConfig = require("../../project.json")
|
|
9
|
+
} catch(err){
|
|
10
|
+
// It's ok
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
let projectSettings = projectConfig.PROJECT
|
|
14
|
+
|
|
15
|
+
// Get settings off story_settings if it exists, otherwise fall back to projectConfig
|
|
16
|
+
let getSettings = function(){
|
|
17
|
+
let settings = projectConfig
|
|
18
|
+
// This needs to be set even if the "try" below fails
|
|
19
|
+
settings.PROJECT['ANALYTICS_CREDIT'] = ''
|
|
20
|
+
// Populate with storySettings if they exist
|
|
21
|
+
let storySettings
|
|
22
|
+
try {
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
// Check for classic story_settings sheet
|
|
26
|
+
[storySettings] = require("../../src/data/story_settings.sheet.json")
|
|
27
|
+
} catch(err){
|
|
28
|
+
try {
|
|
29
|
+
// May be an Archie doc, try grabbing from there
|
|
30
|
+
storySettings = require("../../data/project_data.json").story_settings
|
|
31
|
+
} catch(err) {
|
|
32
|
+
// hacking this to bypass??
|
|
33
|
+
// Evan: This hack has my approval
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
// Populate with sheet settings
|
|
37
|
+
settings = {
|
|
38
|
+
"PAYWALL_SETTING": storySettings.Paywall,
|
|
39
|
+
"EMBEDDED": projectConfig.EMBEDDED,
|
|
40
|
+
"GOOGLE_SHEETS": projectConfig.GOOGLE_SHEETS,
|
|
41
|
+
"GOOGLE_DOCS": projectConfig.GOOGLE_DOCS,
|
|
42
|
+
"MAIN_DOMAIN": projectConfig.MAIN_DOMAIN,
|
|
43
|
+
"PROJECT": {
|
|
44
|
+
"SUBFOLDER": storySettings.Year,
|
|
45
|
+
"SLUG": storySettings.Slug,
|
|
46
|
+
"TITLE": storySettings.SEO_Title,
|
|
47
|
+
"DISPLAY_TITLE": storySettings.Title,
|
|
48
|
+
"SOCIAL_TITLE": storySettings.Social_Title,
|
|
49
|
+
"DECK": storySettings.Deck,
|
|
50
|
+
"URL": "https://projects.sfchronicle.com",
|
|
51
|
+
"IMAGE": "https://s.hdnux.com/photos/0/0/0/0/"+storySettings.Social_ImageID+"/1/1600x0.jpg",
|
|
52
|
+
"DESCRIPTION": storySettings.SEO_Description,
|
|
53
|
+
"TWITTER_TEXT": storySettings.Twitter_Text,
|
|
54
|
+
"DATE": storySettings.Publish_Date,
|
|
55
|
+
"MOD_DATE": storySettings.Mod_Date || storySettings.LastModDate_C2P,
|
|
56
|
+
"AUTHORS": projectSettings.AUTHORS,
|
|
57
|
+
"ANALYTICS_CREDIT": storySettings.Analytics_Credit,
|
|
58
|
+
"HEARST_CATEGORY": storySettings.Category || storySettings.Analytics_Section || "News",
|
|
59
|
+
"KEY_SUBJECTS": storySettings.Key_Subjects || "",
|
|
60
|
+
"MARKET_KEY": storySettings.Market_Key,
|
|
61
|
+
// Surveys have slightly different naming, so catch that below for backwards compat
|
|
62
|
+
"NEWSLETTER_ID": storySettings.NewsletterID || storySettings.Custom_Sailthru_ID || projectSettings.NEWSLETTER_ID,
|
|
63
|
+
"NEWSLETTER_PROMO": storySettings.NewsletterPromo || storySettings.Custom_Signup_Text || projectSettings.NEWSLETTER_PROMO,
|
|
64
|
+
"NEWSLETTER_LEGAL": storySettings.NewsletterLegal || storySettings.TOS_Text || projectSettings.NEWSLETTER_LEGAL,
|
|
65
|
+
"RELATED_LINKS_HED": storySettings.Related_Links_Hed
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
} catch (err){
|
|
69
|
+
// It's ok, we'll use project data
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Check if we need a slash
|
|
73
|
+
let slash = "";
|
|
74
|
+
if (settings.PROJECT.SUBFOLDER){
|
|
75
|
+
slash = "/"
|
|
76
|
+
}
|
|
77
|
+
settings.PROJECT['OPT_SLASH'] = slash
|
|
78
|
+
// Set the canonical (either from the sheet override or constructed)
|
|
79
|
+
settings.PROJECT['CANONICAL_URL'] = projectConfig.MAIN_DOMAIN + "/" + settings.PROJECT.SUBFOLDER + slash + settings.PROJECT.SLUG
|
|
80
|
+
if (typeof storySettings !== "undefined" && storySettings.Canonical_URL){
|
|
81
|
+
settings.PROJECT['CANONICAL_URL'] = storySettings.Canonical_URL
|
|
82
|
+
}
|
|
83
|
+
return settings
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
module.exports = { getSettings }
|