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
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
var { google } = require("googleapis");
|
|
4
|
+
var opn = require("opn");
|
|
5
|
+
|
|
6
|
+
var http = require("http");
|
|
7
|
+
var os = require("os");
|
|
8
|
+
var path = require("path");
|
|
9
|
+
var url = require("url");
|
|
10
|
+
var fs = require("fs");
|
|
11
|
+
var writeFile = require('write');
|
|
12
|
+
|
|
13
|
+
// Prep the service account for drive
|
|
14
|
+
var serviceAccountCreds = path.join(os.homedir(), "service-account-google-creds.json");
|
|
15
|
+
var tokenLocation = path.join(os.homedir(), ".google_oauth_token");
|
|
16
|
+
|
|
17
|
+
var fallbackAuth = function() {
|
|
18
|
+
// If it's coming from EC2, pull from project
|
|
19
|
+
if (process.env.GOOGLE_OAUTH_SYSTEM === "EC2"){
|
|
20
|
+
tokenLocation = "../.google_oauth_token";
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
var tokens = fs.readFileSync(tokenLocation, "utf-8");
|
|
25
|
+
tokens = JSON.parse(tokens);
|
|
26
|
+
auth = new google.auth.OAuth2(process.env.GOOGLE_OAUTH_CLIENT_ID, process.env.GOOGLE_OAUTH_CONSUMER_SECRET);
|
|
27
|
+
auth.setCredentials(tokens);
|
|
28
|
+
|
|
29
|
+
auth.on("tokens", function(update) {
|
|
30
|
+
Object.assign(tokens, update);
|
|
31
|
+
fs.writeFileSync(tokenLocation, JSON.stringify(tokens, null, 2));
|
|
32
|
+
});
|
|
33
|
+
} catch(err){
|
|
34
|
+
// If we error here, fire up local (as long as we're on on EC2)
|
|
35
|
+
if (process.env.GOOGLE_OAUTH_SYSTEM !== "EC2"){
|
|
36
|
+
task()
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return auth;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
var authenticate = function({fallback}) {
|
|
43
|
+
if (fallback){
|
|
44
|
+
return new Promise((resolve, reject) => {
|
|
45
|
+
console.log("Service account failed, falling back to regular token (to use the service account, share this sheet or doc with sfchronicle-gatsby@zinc-proton-250521.iam.gserviceaccount.com)")
|
|
46
|
+
resolve(fallbackAuth());
|
|
47
|
+
})
|
|
48
|
+
}
|
|
49
|
+
// Try to use the service account first
|
|
50
|
+
return new Promise((resolve, reject) => {
|
|
51
|
+
try {
|
|
52
|
+
// If it's coming from EC2, pull from project
|
|
53
|
+
if (process.env.GOOGLE_OAUTH_SYSTEM === "EC2"){
|
|
54
|
+
serviceAccountCreds = "../service-account-google-creds.json";
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
var serviceAccountJSON = fs.readFileSync(serviceAccountCreds, "utf-8");
|
|
58
|
+
serviceAccountJSON = JSON.parse(serviceAccountJSON);
|
|
59
|
+
|
|
60
|
+
// configure a JWT auth client
|
|
61
|
+
let jwtClient = new google.auth.JWT(
|
|
62
|
+
serviceAccountJSON.client_email,
|
|
63
|
+
null,
|
|
64
|
+
serviceAccountJSON.private_key,
|
|
65
|
+
[
|
|
66
|
+
'https://www.googleapis.com/auth/spreadsheets',
|
|
67
|
+
'https://www.googleapis.com/auth/drive'
|
|
68
|
+
]
|
|
69
|
+
);
|
|
70
|
+
//authenticate request
|
|
71
|
+
jwtClient.authorize(function (err, tokens) {
|
|
72
|
+
if (err) {
|
|
73
|
+
console.log("Stage 1 error, fallback auth");
|
|
74
|
+
resolve(fallbackAuth());
|
|
75
|
+
} else {
|
|
76
|
+
console.log("Successfully connected to service account!");
|
|
77
|
+
// Return the jwtClient as auth
|
|
78
|
+
resolve(jwtClient);
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
} catch (err){
|
|
82
|
+
// It's ok if it errors, we have the fallback
|
|
83
|
+
console.log("Stage 2 error, fallback auth");
|
|
84
|
+
resolve(fallbackAuth());
|
|
85
|
+
}
|
|
86
|
+
})
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
var task = function() {
|
|
90
|
+
// var done = this.async();
|
|
91
|
+
|
|
92
|
+
var clientID = process.env.GOOGLE_OAUTH_CLIENT_ID;
|
|
93
|
+
var secret = process.env.GOOGLE_OAUTH_CONSUMER_SECRET;
|
|
94
|
+
|
|
95
|
+
var client = new google.auth.OAuth2(clientID, secret, "http://localhost:8000/authenticate/");
|
|
96
|
+
google.options({
|
|
97
|
+
auth: client
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
var scopes = [
|
|
101
|
+
"https://www.googleapis.com/auth/drive",
|
|
102
|
+
"https://www.googleapis.com/auth/spreadsheets"
|
|
103
|
+
];
|
|
104
|
+
|
|
105
|
+
var authURL = client.generateAuthUrl({
|
|
106
|
+
access_type: "offline",
|
|
107
|
+
scope: scopes.join(" "),
|
|
108
|
+
prompt: "consent"
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
var onRequest = function(request, response) {
|
|
112
|
+
response.setHeader("Connection", "close");
|
|
113
|
+
if (request.url.indexOf("authenticate") > -1) {
|
|
114
|
+
return onAuthenticated(request, response);
|
|
115
|
+
} else if (request.url.indexOf("authorize") > -1) {
|
|
116
|
+
response.setHeader("Location", authURL);
|
|
117
|
+
response.writeHead(302);
|
|
118
|
+
} else {
|
|
119
|
+
response.writeHead(404);
|
|
120
|
+
}
|
|
121
|
+
response.end();
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
var onAuthenticated = async function(request, response) {
|
|
125
|
+
var requestURL = request.url[0] == "/" ? "localhost:8000" + request.url : request.url;
|
|
126
|
+
var query = new url.URL(requestURL).searchParams;
|
|
127
|
+
var code = query.get("code");
|
|
128
|
+
if (!code) return;
|
|
129
|
+
try {
|
|
130
|
+
var token = await client.getToken(code);
|
|
131
|
+
var tokens = token.tokens;
|
|
132
|
+
writeFile(tokenLocation, JSON.stringify(tokens, null, 2), function(err) {
|
|
133
|
+
if (err) {
|
|
134
|
+
console.log(err);
|
|
135
|
+
} else {
|
|
136
|
+
console.log("Authenticated");
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
response.end("Done! Now run your command again.");
|
|
140
|
+
} catch (err) {
|
|
141
|
+
response.end(err);
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
var server = http.createServer(onRequest);
|
|
146
|
+
server.listen(8000, () => opn("http://localhost:8000/authorize"));
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
let fullAuth = {
|
|
150
|
+
task: task,
|
|
151
|
+
authenticate: authenticate
|
|
152
|
+
}
|
|
153
|
+
module.exports = fullAuth;
|
package/copy/sheets.js
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Uses the Google Sheets API to pull data from Sheets and load it onto shared
|
|
3
|
+
* state. Writes the data out to JSON for later reference. Does not currently
|
|
4
|
+
* check for existing data to merge--it does a fresh pull every time.
|
|
5
|
+
* Sheets must be shared with the service account email before they can be accessed with this task
|
|
6
|
+
* @param {object} project standard object from project-config.json or project.json
|
|
7
|
+
* @param {string} directory optional alternate path to directory in which to save the output
|
|
8
|
+
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
var { google } = require("googleapis");
|
|
12
|
+
var api = google.sheets("v4");
|
|
13
|
+
var writeFile = require("write");
|
|
14
|
+
var authObj = require("./googleauth");
|
|
15
|
+
|
|
16
|
+
var cast = function (str, forceStr) {
|
|
17
|
+
if (!forceStr){
|
|
18
|
+
if (typeof str !== "string") {
|
|
19
|
+
if (typeof str.value == "string") {
|
|
20
|
+
str = str.value;
|
|
21
|
+
} else {
|
|
22
|
+
return str;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (str.match(/^-?(0?\.|[1-9])[\d\.]*$/) || str == "0") {
|
|
26
|
+
var n = Number(str);
|
|
27
|
+
if (isNaN(n)) return str;
|
|
28
|
+
return n;
|
|
29
|
+
}
|
|
30
|
+
if (str.toLowerCase() == "true" || str.toLowerCase() == "false") {
|
|
31
|
+
return str.toLowerCase() == "true" ? true : false;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
// To force string, just return string
|
|
35
|
+
|
|
36
|
+
return str;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
let googleAuth = (project, directory = null, forceStr = false) => {
|
|
40
|
+
var auth = null;
|
|
41
|
+
authObj
|
|
42
|
+
.authenticate({ fallback: false })
|
|
43
|
+
.then((resp) => {
|
|
44
|
+
auth = resp;
|
|
45
|
+
grabSheets(auth, project, directory, forceStr).catch(() => {
|
|
46
|
+
// If the first attempt failed, then make another req using the fallback
|
|
47
|
+
authObj.authenticate({ fallback: true }).then((resp) => {
|
|
48
|
+
auth = resp;
|
|
49
|
+
grabSheets(auth, project, directory, forceStr);
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
})
|
|
53
|
+
.catch(() => {
|
|
54
|
+
// Failure if we fall back but there's no token
|
|
55
|
+
auth = authObj.task();
|
|
56
|
+
grabSheets(auth, project, directory, forceStr);
|
|
57
|
+
});
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
let grabSheets = (auth, project, directory, forceStr) => {
|
|
61
|
+
return new Promise((resolveAll, rejectAll) => {
|
|
62
|
+
var sheetKeys = project.GOOGLE_SHEETS;
|
|
63
|
+
if (!sheetKeys){
|
|
64
|
+
// Try the old way
|
|
65
|
+
sheetKeys = project.sheets;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (!sheetKeys || !sheetKeys.length) {
|
|
69
|
+
console.log(
|
|
70
|
+
"You must specify a spreadsheet key in project.json or auth.json!"
|
|
71
|
+
);
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
let promiseStack = [];
|
|
76
|
+
for (var spreadsheetId of sheetKeys) {
|
|
77
|
+
let promiseItem = new Promise((resolve, reject) => {
|
|
78
|
+
getSheet(resolve, reject, auth, spreadsheetId, directory, forceStr);
|
|
79
|
+
});
|
|
80
|
+
promiseStack.push(promiseItem);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
Promise.all(promiseStack)
|
|
84
|
+
.then(() => {
|
|
85
|
+
// Resolve the whole thing
|
|
86
|
+
resolveAll();
|
|
87
|
+
})
|
|
88
|
+
.catch(() => {
|
|
89
|
+
// If this was triggered, reject all to fall back
|
|
90
|
+
rejectAll();
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
let getSheet = async (resolve, reject, auth, spreadsheetId, directory, forceStr) => {
|
|
96
|
+
let output = await api.spreadsheets
|
|
97
|
+
.get({
|
|
98
|
+
auth,
|
|
99
|
+
spreadsheetId,
|
|
100
|
+
})
|
|
101
|
+
.catch(() => {
|
|
102
|
+
// This might fail if we don't have access
|
|
103
|
+
reject();
|
|
104
|
+
});
|
|
105
|
+
if (!output) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
var book = output.data;
|
|
109
|
+
var { sheets, spreadsheetId } = book;
|
|
110
|
+
for (var sheet of sheets) {
|
|
111
|
+
if (sheet.properties.title[0] == "_") continue;
|
|
112
|
+
var response = await api.spreadsheets.values.get({
|
|
113
|
+
auth,
|
|
114
|
+
spreadsheetId,
|
|
115
|
+
range: `${sheet.properties.title}!A:AAA`,
|
|
116
|
+
majorDimension: "ROWS",
|
|
117
|
+
});
|
|
118
|
+
var { values } = response.data;
|
|
119
|
+
var header = values.shift();
|
|
120
|
+
var isKeyed = header.indexOf("key") > -1;
|
|
121
|
+
var isValued = header.indexOf("value") > -1;
|
|
122
|
+
var out = isKeyed ? {} : [];
|
|
123
|
+
for (var row of values) {
|
|
124
|
+
// skip blank rows
|
|
125
|
+
if (!row.length) continue;
|
|
126
|
+
var obj = {};
|
|
127
|
+
row.forEach(function (value, i) {
|
|
128
|
+
var key = header[i];
|
|
129
|
+
obj[key] = cast(value, forceStr);
|
|
130
|
+
});
|
|
131
|
+
if (isKeyed) {
|
|
132
|
+
out[obj.key] = isValued ? obj.value : obj;
|
|
133
|
+
} else {
|
|
134
|
+
out.push(obj);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
//set alternate dir if we have it
|
|
139
|
+
directory = directory || "src/data/";
|
|
140
|
+
var file_path = `${directory}${sheet.properties.title.replace(
|
|
141
|
+
/\s+/g,
|
|
142
|
+
"_"
|
|
143
|
+
)}.sheet.json`;
|
|
144
|
+
console.log(`Saving sheet to ${file_path}`);
|
|
145
|
+
// grunt.file.write(filename, JSON.stringify(out, null, 2));
|
|
146
|
+
writeFile(file_path, JSON.stringify(out, null, 2));
|
|
147
|
+
resolve(file_path);
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
module.exports = { googleAuth };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// There are additional weights and versions of these fonts available,
|
|
2
|
+
// but adding them makes the client download larger
|
|
3
|
+
@font-face {
|
|
4
|
+
font-family: 'ChronicleDispCond-Black';
|
|
5
|
+
font-display: swap;
|
|
6
|
+
font-style: normal;
|
|
7
|
+
font-weight: 400;
|
|
8
|
+
src: local("ChronicleDispCond-Black"),url("https://www.timesunion.com/css/core/fonts/chronicle/ChronicleDispCond-Black_Web.woff2") format("woff2"), url("https://www.timesunion.com/css/core/fonts/chronicle/ChronicleDispCond-Black_Web.woff") format("woff");
|
|
9
|
+
}
|
|
10
|
+
@font-face {
|
|
11
|
+
font-family: 'ChronicleDispCond-Roman';
|
|
12
|
+
font-display: swap;
|
|
13
|
+
font-style: normal;
|
|
14
|
+
font-weight: 400;
|
|
15
|
+
src: local('ChronicleDispCond-Roman'), url("https://www.timesunion.com/css/core/fonts/chronicle/ChronicleDispCond-Roman_Web.woff2") format('woff2'), url("https://www.timesunion.com/css/core/fonts/chronicle/ChronicleDispCond-Roman_Web.woff") format('woff');
|
|
16
|
+
}
|
|
17
|
+
@font-face {
|
|
18
|
+
font-family: 'ChronicleTextG2-Roman';
|
|
19
|
+
font-display: swap;
|
|
20
|
+
font-style: normal;
|
|
21
|
+
font-weight: 400;
|
|
22
|
+
src: local('ChronicleTextG2-Roman'), url("https://www.timesunion.com/css/core/fonts/chronicle/ChronicleTextG2-Roman_Web.woff2") format('woff2'), url("https://www.timesunion.com/css/core/fonts/chronicle/ChronicleTextG2-Roman_Web.woff") format('woff');
|
|
23
|
+
}
|
|
24
|
+
@font-face {
|
|
25
|
+
font-family: 'ChronicleTextG2-Bold';
|
|
26
|
+
font-display: swap;
|
|
27
|
+
font-style: normal;
|
|
28
|
+
font-weight: 400;
|
|
29
|
+
src: local('ChronicleTextG2-Bold'), url("https://www.timesunion.com/css/core/fonts/chronicle/ChronicleTextG2-Bold_Web.woff2") format('woff2'), url("https://www.timesunion.com/css/core/fonts/chronicle/ChronicleTextG2-Bold_Web.woff") format('woff');
|
|
30
|
+
}
|
|
31
|
+
@font-face {
|
|
32
|
+
font-family: 'HelveticaNeue-Roman';
|
|
33
|
+
font-display: swap;
|
|
34
|
+
font-style: normal;
|
|
35
|
+
font-weight: 400;
|
|
36
|
+
src: local('HelveticaNeue-Roman'), url("https://www.timesunion.com/css/core/fonts/neuehelvetica/HelveticaNeue-Roman.woff2") format('woff2'), url("https://www.timesunion.com/css/core/fonts/neuehelvetica/HelveticaNeue-Roman.woff") format('woff');
|
|
37
|
+
}
|
|
38
|
+
@font-face {
|
|
39
|
+
font-family: 'HelveticaNeue-HeavyCond';
|
|
40
|
+
font-display: swap;
|
|
41
|
+
font-style: normal;
|
|
42
|
+
font-weight: 400;
|
|
43
|
+
src: local('HelveticaNeue-HeavyCond'), url("https://www.timesunion.com/css/core/fonts/neuehelvetica/HelveticaNeue-HeavyCond.woff2") format('woff2'), url("https://www.timesunion.com/css/core/fonts/neuehelvetica/HelveticaNeue-HeavyCond.woff") format('woff');
|
|
44
|
+
}
|
|
45
|
+
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// The brand fonts
|
|
2
|
+
@font-face {
|
|
3
|
+
font-family: 'Lora Bold';
|
|
4
|
+
font-display: swap;
|
|
5
|
+
font-style: normal;
|
|
6
|
+
font-weight: 400;
|
|
7
|
+
src: local('Lora Bold'), url("https://www.sfchronicle.com/css/core/fonts/lora/lora-v12-latin-700.woff2") format('woff2'), url("https://www.sfchronicle.com/css/core/fonts/lora/lora-v12-latin-700.woff") format('woff');
|
|
8
|
+
}
|
|
9
|
+
@font-face {
|
|
10
|
+
font-family: 'Lora Regular';
|
|
11
|
+
font-display: swap;
|
|
12
|
+
font-style: normal;
|
|
13
|
+
font-weight: 400;
|
|
14
|
+
src: local('Lora Regular'), url("https://www.sfchronicle.com/css/core/fonts/lora/lora-v12-latin-regular.woff2") format('woff2'), url("https://www.sfchronicle.com/css/core/fonts/lora/lora-v12-latin-regular.woff") format('woff');
|
|
15
|
+
}
|
|
16
|
+
@font-face {
|
|
17
|
+
font-family: 'Lora Light';
|
|
18
|
+
font-display: swap;
|
|
19
|
+
font-style: normal;
|
|
20
|
+
font-weight: 300;
|
|
21
|
+
src: local('Lora Light'), url("https://www.sfchronicle.com/css/core/fonts/lora/lora-v12-latin-regular.woff2") format('woff2'), url("https://www.sfchronicle.com/css/core/fonts/lora/lora-v12-latin-regular.woff") format('woff');
|
|
22
|
+
}
|
|
23
|
+
@font-face {
|
|
24
|
+
font-family: 'Source Sans Pro Light';
|
|
25
|
+
font-display: swap;
|
|
26
|
+
font-style: normal;
|
|
27
|
+
font-weight: 300;
|
|
28
|
+
src: local('Source Sans Pro Regular'), url("https://www.sfchronicle.com/css/core/fonts/sourcesans/source-sans-pro-v11-latin-300.woff2") format('woff2'), url("https://www.sfchronicle.com/css/core/fonts/sourcesans/source-sans-pro-v11-latin-300.woff") format('woff');
|
|
29
|
+
}
|
|
30
|
+
@font-face {
|
|
31
|
+
font-family: 'Source Sans Pro Regular';
|
|
32
|
+
font-display: swap;
|
|
33
|
+
font-style: normal;
|
|
34
|
+
font-weight: 400;
|
|
35
|
+
src: local('Source Sans Pro Regular'), url("https://www.sfchronicle.com/css/core/fonts/sourcesans/source-sans-pro-v11-latin-regular.woff2") format('woff2'), url("https://www.sfchronicle.com/css/core/fonts/sourcesans/source-sans-pro-v11-latin-regular.woff") format('woff');
|
|
36
|
+
}
|
|
37
|
+
@font-face {
|
|
38
|
+
font-family: 'Source Sans Pro Semibold';
|
|
39
|
+
font-display: swap;
|
|
40
|
+
font-style: normal;
|
|
41
|
+
font-weight: 600;
|
|
42
|
+
src: local('Source Sans Pro Semibold'), url("https://www.sfchronicle.com/css/core/fonts/sourcesans/source-sans-pro-v11-latin-600.woff2") format('woff2'), url("https://www.sfchronicle.com/css/core/fonts/sourcesans/source-sans-pro-v11-latin-600.woff") format('woff');
|
|
43
|
+
}
|
|
44
|
+
@font-face {
|
|
45
|
+
font-family: 'Source Sans Pro Bold';
|
|
46
|
+
font-display: swap;
|
|
47
|
+
font-style: normal;
|
|
48
|
+
font-weight: 700;
|
|
49
|
+
src: local('Source Sans Pro Bold'), url("https://www.sfchronicle.com/css/core/fonts/sourcesans/source-sans-pro-v11-latin-700.woff2") format('woff2'), url("https://www.sfchronicle.com/css/core/fonts/sourcesans/source-sans-pro-v11-latin-700.woff") format('woff');
|
|
50
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// There are additional weights and versions of these fonts available,
|
|
2
|
+
// but adding them makes the client download larger
|
|
3
|
+
@font-face {
|
|
4
|
+
font-family: 'Marr Sans Semibold';
|
|
5
|
+
font-display: swap;
|
|
6
|
+
font-style: normal;
|
|
7
|
+
font-weight: 400;
|
|
8
|
+
src: local('Marr Sans Semibold'), url("https://www.houstonchronicle.com/css/core/fonts/marrsans/MarrSans-Semibold-Web.woff2") format('woff2'), url("https://www.houstonchronicle.com/css/core/fonts/marrsans/MarrSans-Semibold-Web.woff") format('woff');
|
|
9
|
+
}
|
|
10
|
+
@font-face {
|
|
11
|
+
font-family: 'Marr Sans Regular';
|
|
12
|
+
font-display: swap;
|
|
13
|
+
font-style: normal;
|
|
14
|
+
font-weight: 400;
|
|
15
|
+
src: local('Marr Sans Regular'), url("https://www.houstonchronicle.com/css/core/fonts/marrsans/MarrSans-Regular-Web.woff2") format('woff2'), url("https://www.houstonchronicle.com/css/core/fonts/marrsans/MarrSans-Regular-Web.woff") format('woff');
|
|
16
|
+
}
|
|
17
|
+
@font-face {
|
|
18
|
+
font-family: 'Marr Sans Condensed Medium';
|
|
19
|
+
font-display: swap;
|
|
20
|
+
font-style: normal;
|
|
21
|
+
font-weight: 400;
|
|
22
|
+
src: local("Marr Sans Condensed Medium"),url("https://www.houstonchronicle.com/css/core/fonts/marrsans/MarrSansCondensed-Medium-Web.woff2") format("woff2"), url("https://www.houstonchronicle.com/css/core/fonts/marrsans/MarrSansCondensed-Medium-Web.woff") format("woff");
|
|
23
|
+
}
|
|
24
|
+
@font-face {
|
|
25
|
+
font-family: 'Marr Sans Condensed Semibold';
|
|
26
|
+
font-display: swap;
|
|
27
|
+
font-style: normal;
|
|
28
|
+
font-weight: 400;
|
|
29
|
+
src: local("Marr Sans Condensed Semibold"),url("https://www.houstonchronicle.com/css/core/fonts/marrsans/MarrSansCondensed-Semibold-Web.woff2") format("woff2"), url("https://www.houstonchronicle.com/css/core/fonts/marrsans/MarrSansCondensed-Semibold-Web.woff") format("woff");
|
|
30
|
+
}
|
|
31
|
+
@font-face {
|
|
32
|
+
font-family: 'Publico Text Roman';
|
|
33
|
+
font-display: swap;
|
|
34
|
+
font-style: normal;
|
|
35
|
+
font-weight: 400;
|
|
36
|
+
src: local('Publico Text Roman'), url("https://www.houstonchronicle.com/css/core/fonts/publico/PublicoText-Roman-Web.woff2") format('woff2'), url("https://www.houstonchronicle.com/css/core/fonts/publico/PublicoText-Roman-Web.woff") format('woff');
|
|
37
|
+
}
|
|
38
|
+
@font-face {
|
|
39
|
+
font-family: 'Publico Text Bold';
|
|
40
|
+
font-display: swap;
|
|
41
|
+
font-style: normal;
|
|
42
|
+
font-weight: 400;
|
|
43
|
+
src: local('Publico Text Bold'), url("https://www.houstonchronicle.com/css/core/fonts/publico/PublicoText-Bold-Web.woff2") format('woff2'), url("https://www.houstonchronicle.com/css/core/fonts/publico/PublicoText-Bold-Web.woff") format('woff');
|
|
44
|
+
}
|
|
45
|
+
@font-face {
|
|
46
|
+
font-family: 'Publico Headline Medium';
|
|
47
|
+
font-display: swap;
|
|
48
|
+
font-style: normal;
|
|
49
|
+
font-weight: 400;
|
|
50
|
+
src: local('Publico Headline Medium'), url("https://www.houstonchronicle.com/css/core/fonts/publico/PublicoHeadline-Medium-Web.woff2") format('woff2'), url("https://www.houstonchronicle.com/css/core/fonts/publico/PublicoHeadline-Medium-Web.woff") format('woff');
|
|
51
|
+
}
|
package/fonts/sfc.less
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// The brand fonts
|
|
2
|
+
@font-face {
|
|
3
|
+
font-family: 'National Bold';
|
|
4
|
+
font-display: swap;
|
|
5
|
+
font-style: normal;
|
|
6
|
+
font-weight: 400;
|
|
7
|
+
src: local('National Bold'), url("https://www.sfchronicle.com/css/core/fonts/national/NationalWeb-Bold.woff2") format('woff2'), url("https://www.sfchronicle.com/css/core/fonts/national/NationalWeb-Bold.woff") format('woff');
|
|
8
|
+
}
|
|
9
|
+
@font-face {
|
|
10
|
+
font-family: 'National Medium';
|
|
11
|
+
font-display: swap;
|
|
12
|
+
font-style: normal;
|
|
13
|
+
font-weight: 400;
|
|
14
|
+
src: local('National Medium'), url("https://www.sfchronicle.com/css/core/fonts/national/NationalWeb-Medium.woff2") format('woff2'), url("https://www.sfchronicle.com/css/core/fonts/national/NationalWeb-Medium.woff") format('woff');
|
|
15
|
+
}
|
|
16
|
+
@font-face {
|
|
17
|
+
font-family: 'National Light';
|
|
18
|
+
font-display: swap;
|
|
19
|
+
font-style: normal;
|
|
20
|
+
font-weight: 400;
|
|
21
|
+
src: local('National Light'), url("https://www.sfchronicle.com/css/core/fonts/national/NationalWeb-Light.woff2") format('woff2'), url("https://www.sfchronicle.com/css/core/fonts/national/NationalWeb-Light.woff") format('woff');
|
|
22
|
+
}
|
|
23
|
+
@font-face {
|
|
24
|
+
font-family: 'National Book';
|
|
25
|
+
font-display: swap;
|
|
26
|
+
font-style: normal;
|
|
27
|
+
font-weight: 400;
|
|
28
|
+
src: local('National Book'), url("https://www.sfchronicle.com/css/core/fonts/national/NationalWeb-Book.woff2") format('woff2'), url("https://www.sfchronicle.com/css/core/fonts/national/NationalWeb-Book.woff") format('woff');
|
|
29
|
+
}
|
|
30
|
+
@font-face {
|
|
31
|
+
font-family: 'Tiempos Regular';
|
|
32
|
+
font-display: swap;
|
|
33
|
+
font-style: normal;
|
|
34
|
+
font-weight: 400;
|
|
35
|
+
src: local('Tiempos Regular'), url("https://www.sfchronicle.com/css/core/fonts/tiempos/TiemposTextWeb-Regular.woff2") format('woff2'), url("https://www.sfchronicle.com/css/core/fonts/tiempos/TiemposTextWeb-Regular.woff") format('woff');
|
|
36
|
+
}
|
|
37
|
+
@font-face {
|
|
38
|
+
font-family: 'Tiempos Bold';
|
|
39
|
+
font-display: swap;
|
|
40
|
+
font-style: normal;
|
|
41
|
+
font-weight: 400;
|
|
42
|
+
src: local('Tiempos Bold'), url("https://www.sfchronicle.com/css/core/fonts/tiempos/TiemposTextWeb-Bold.woff2") format('woff2'), url("https://www.sfchronicle.com/css/core/fonts/tiempos/TiemposTextWeb-Bold.woff") format('woff');
|
|
43
|
+
}
|
|
44
|
+
@font-face {
|
|
45
|
+
font-family: 'Tiempos Headline Light';
|
|
46
|
+
font-display: swap;
|
|
47
|
+
font-style: normal;
|
|
48
|
+
font-weight: 400;
|
|
49
|
+
src: local('Tiempos Headline Light'), url("https://www.sfchronicle.com/css/core/fonts/tiempos/TiemposHeadlineWeb-Light.woff2") format('woff2'), url("https://www.sfchronicle.com/css/core/fonts/tiempos/TiemposHeadlineWeb-Light.woff") format('woff');
|
|
50
|
+
}
|
|
51
|
+
@font-face {
|
|
52
|
+
font-family: 'Tiempos Headline Black';
|
|
53
|
+
font-display: swap;
|
|
54
|
+
font-style: normal;
|
|
55
|
+
font-weight: 400;
|
|
56
|
+
src: local("Tiempos Headline Black"),url(https://www.sfchronicle.com/css/core/fonts/tiempos/TiemposHeadlineWeb-Black.woff2) format("woff2"), url("https://www.sfchronicle.com/css/core/fonts/tiempos/TiemposHeadlineWeb-Black.woff") format("woff");
|
|
57
|
+
}
|