sfc-utils 1.3.64 → 1.3.66

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.
@@ -3,62 +3,49 @@
3
3
  import React, { Fragment, useEffect } from 'react'
4
4
  import PropTypes from 'prop-types'
5
5
  import { Helmet } from 'react-helmet'
6
-
7
- // Bring in footer
6
+ import LayoutHelmet from '../../../components/layout/layouthelmet.mjs'
8
7
  import Footer from './sfc/footer'
9
-
10
8
  // Add SFC utils
11
- import { blendHDN, appCheck, getBrands, getBlueconic } from '../../../index'
12
-
9
+ import { appCheck } from '../../../index'
10
+ import { appendLayoutScripts, formatHDN } from "../../../components/helpers/utilfunctions.mjs"
13
11
  // Import global styles needed in document
14
12
  require('../styles/seed.less')
15
13
 
16
- const Layout = ({
14
+ const Layout = ({
17
15
  meta,
18
16
  url_add = '',
19
17
  description = false,
20
18
  image = false,
21
19
  social_title = false,
22
20
  title = false,
23
- children,
21
+ embed = false,
22
+ children,
24
23
  }) => {
25
24
  // Determine if we need registration code
26
25
 
27
26
  let {
28
27
  EMBEDDED,
29
- MAIN_DOMAIN,
30
28
  PROJECT: {
31
- AUTHORS,
32
29
  DESCRIPTION,
33
30
  IMAGE,
34
- ISO_MODDATE,
35
- ISO_PUBDATE,
36
- OPT_SLASH,
37
- SLUG,
38
31
  SOCIAL_TITLE,
39
- SUBFOLDER,
40
- TITLE,
41
- MARKET_KEY,
42
- CANONICAL_URL
32
+ TITLE
43
33
  },
44
34
  } = meta
45
35
 
46
36
  // Override these if they exist (but just use the default otherwise)
47
- DESCRIPTION = description || DESCRIPTION
48
- IMAGE = image || IMAGE
49
- SOCIAL_TITLE = social_title || SOCIAL_TITLE
50
- TITLE = title || TITLE
51
-
52
- let styleSheetID;
53
- if ((MARKET_KEY === "SFC") || (MARKET_KEY === "Houston") || (MARKET_KEY === "Albany")) {
54
- styleSheetID = MARKET_KEY
55
- }
56
- else {
57
- styleSheetID = "default"
37
+ meta.PROJECT.DESCRIPTION = description || DESCRIPTION
38
+ meta.PROJECT.IMAGE = image || IMAGE
39
+ meta.PROJECT.SOCIAL_TITLE = social_title || SOCIAL_TITLE
40
+ meta.PROJECT.TITLE = title || TITLE
41
+
42
+ // If we're receiving `embed` as a prop, change this page's settings to be embed settings
43
+ if (embed) {
44
+ meta.EMBEDDED = true
58
45
  }
59
46
 
60
47
  // Make sure url_add ends with a slash
61
- if (url_add && url_add.slice(-1) !== "/"){
48
+ if (url_add && url_add.slice(-1) !== "/") {
62
49
  url_add += "/"
63
50
  }
64
51
 
@@ -67,77 +54,10 @@ const Layout = ({
67
54
  const isApp = appCheck()
68
55
 
69
56
  // Combine our settings with what Hearst puts on page
70
- let stringHDN = ''
71
- if (!EMBEDDED) {
72
- // Put url_add into a new meta object to pass in
73
- const metaHDN = Object.assign({}, meta)
74
- metaHDN.URL_ADD = url_add
75
- // Make sure this is free on app
76
- if (isApp){
77
- metaHDN.PAYWALL_SETTING = "free";
78
- }
79
- let blended = blendHDN(metaHDN)
80
- stringHDN = blended.stringHDN
81
- }
82
-
83
- // Get brand vars
84
- const thisBrand = getBrands(MARKET_KEY);
85
-
86
- // Handle author data
87
- let authorObj = []
88
- let newAuthor = {}
89
- try {
90
- AUTHORS.forEach(author => {
91
- newAuthor = {
92
- '@type': 'Person',
93
- name: author.AUTHOR_NAME,
94
- url: author.AUTHOR_PAGE,
95
- }
96
- authorObj.push(newAuthor)
97
- })
98
- } catch (err) {
99
- // If it errored, just set to neutral default
100
- authorObj = {
101
- '@type': 'Person',
102
- name: thisBrand.attributes.siteName,
103
- url: MAIN_DOMAIN,
104
- }
105
- }
57
+ let stringHDN = formatHDN(EMBEDDED, url_add, meta);
106
58
 
107
59
  useEffect(() => {
108
- // React Helmet is actually terrible and runs these scripts twice, so we are including them async ourselves
109
- // Run analytics and resizing scripts right away so we take care of that
110
- if (!EMBEDDED){
111
- let script = document.createElement('script');
112
- script.type = 'text/javascript';
113
- script.src = 'https://nexus.ensighten.com/hearst/news/Bootstrap.js';
114
- document.body.appendChild(script);
115
- } else {
116
- let script = document.createElement('script');
117
- script.type = 'text/javascript';
118
- script.src = 'https://projects.sfchronicle.com/shared/js/responsive-child.js';
119
- document.body.appendChild(script);
120
- }
121
-
122
- if (!EMBEDDED && !isApp){
123
- let script = document.createElement('script');
124
- script.type = 'text/javascript';
125
- script.id = 'adPositionManagerScriptTag';
126
- script.src = 'https://aps.hearstnp.com/Scripts/loadAds.js';
127
- document.body.appendChild(script);
128
- }
129
-
130
- // Wait a beat, then add to body so it doesn't mess with the head (which Helmet seems to want to manage)
131
- setTimeout(() => {
132
- if (!EMBEDDED && !isApp){
133
- let blueconicURL = getBlueconic(window.location.origin)
134
- let script = document.createElement('script');
135
- script.type = 'text/javascript';
136
- script.defer = true;
137
- script.src = blueconicURL;
138
- document.body.appendChild(script);
139
- }
140
- }, 5000)
60
+ appendLayoutScripts(EMBEDDED);
141
61
  }, [])
142
62
 
143
63
  return (
@@ -151,68 +71,8 @@ const Layout = ({
151
71
  },
152
72
  ]}
153
73
  />
154
- <Helmet>
155
- <title>{TITLE}</title>
156
- <meta name="description" content={DESCRIPTION} />
157
- <link
158
- rel="shortcut icon"
159
- href="/favicon.ico"
160
- type="image/x-icon"
161
- />
162
- <link rel="canonical" href={ CANONICAL_URL } />
163
- <link rel="stylesheet" href={`https://files.sfchronicle.com/brand-styles/${styleSheetID}.css`} />
164
-
165
- {(isApp || EMBEDDED) ? (
166
- <meta name="robots" content="noindex, nofollow" />
167
- ) : (
168
- <meta name="robots" content="max-image-preview:large" />
169
- )}
170
-
171
- <meta name="twitter:card" content="summary_large_image" />
172
- <meta name="twitter:title" content={SOCIAL_TITLE} />
173
- <meta name="twitter:site" content={"@"+thisBrand.attributes.twitter} />
174
- <meta
175
- name="twitter:url"
176
- content={`${MAIN_DOMAIN}/${SUBFOLDER}${OPT_SLASH}${SLUG}/${url_add}`}
177
- />
178
- <meta name="twitter:image" content={IMAGE} />
179
- <meta name="twitter:description" content={DESCRIPTION} />
180
74
 
181
- <meta property="og:type" content="article" />
182
- <meta property="og:title" content={SOCIAL_TITLE} />
183
- <meta property="og:site_name" content={thisBrand.attributes.siteName} />
184
- <meta property="og:url" content={`${MAIN_DOMAIN}/${SUBFOLDER}${OPT_SLASH}${SLUG}/${url_add}`}/>
185
- <meta property="og:image" content={IMAGE} />
186
- <meta property="og:description" content={DESCRIPTION} />
187
-
188
- <script data-schema="NewsArticle" type="application/ld+json">{`{
189
- "@context": "http://schema.org",
190
- "@type": "NewsArticle",
191
- "mainEntityOfPage": {
192
- "@type": "WebPage",
193
- "@id": "${MAIN_DOMAIN}/${SUBFOLDER}${OPT_SLASH}${SLUG}/${url_add}"
194
- },
195
- "headline": "${TITLE}",
196
- "image": {
197
- "@type": "ImageObject",
198
- "url": "${IMAGE}"
199
- },
200
- "datePublished": "${ISO_PUBDATE}",
201
- "dateModified": "${ISO_MODDATE}",
202
- "author": ${JSON.stringify(authorObj)},
203
- "publisher": {
204
- "@type": "Organization",
205
- "name": "${thisBrand.attributes.siteName}",
206
- "logo": {
207
- "@type": "ImageObject",
208
- "url": "/apple-touch-icon.png",
209
- "width": "180",
210
- "height": "180"
211
- }
212
- },
213
- "description": "${DESCRIPTION}"
214
- }`}</script>
215
- </Helmet>
75
+ <LayoutHelmet meta={meta} url_add={url_add} />
216
76
 
217
77
  {/* Full project included here: */}
218
78
  {children}
@@ -1,5 +1,6 @@
1
1
  import React from "react"
2
2
  import PropTypes from "prop-types"
3
+ import LayoutScript from "../../components/layout/layoutscript.mjs"
3
4
 
4
5
  export default function HTML(props) {
5
6
  return (
@@ -11,8 +12,7 @@ export default function HTML(props) {
11
12
  name="viewport"
12
13
  content="width=device-width, initial-scale=1, shrink-to-fit=no"
13
14
  />
14
- <script src="https://projects.sfchronicle.com/shared/js/jquery.min.js"></script>
15
- <script src="https://treg.hearstnp.com/treg.js"></script>
15
+ <LayoutScript/>
16
16
  {props.headComponents}
17
17
  </head>
18
18
  <body {...props.bodyAttributes} is="responsive-body">
@@ -5,8 +5,6 @@ import Layout from '../components/layout'
5
5
  import WCMImage from '../components/sfc/wcmimage'
6
6
  import DropCap from '../components/sfc/dropcap'
7
7
  import { useCanNativeLazyLoad } from '../components/sfc/component-helpers/customhooks'
8
- import LazyLoad from 'react-lazyload'
9
- import Topper from '../components/sfc/topper'
10
8
  import RelatedSection from '../components/sfc/relatedsection'
11
9
  import CreditsSection from '../components/sfc/creditssection'
12
10
  import Ad from '../components/sfc/ad'
@@ -37,13 +35,6 @@ try {
37
35
  topperSettings = null;
38
36
  }
39
37
 
40
- // lazy loader wrapper for WCM Image
41
- const LazyLoader = ({children}) => {
42
- return (
43
- <LazyLoad offset={300} resize once>{children}</LazyLoad>
44
- )
45
- }
46
-
47
38
  const IndexPage = ({ data }) => {
48
39
  // easy hooks based request library
49
40
  // const { data: responseData, error } = useSWR('https://api.kanye.rest', getData, {
@@ -63,7 +54,7 @@ const IndexPage = ({ data }) => {
63
54
  return (
64
55
  <Layout meta={siteMetadata}>
65
56
  <NavTop meta={siteMetadata} />
66
- <Topper2 settings={topperSettings[0]} wcmData={allWcmPhotos} lazyloader={LazyLoader}/>
57
+ <Topper2 settings={topperSettings[0]} wcmData={allWcmPhotos}/>
67
58
  <Byline meta={siteMetadata}/>
68
59
  <main>
69
60
  <article>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sfc-utils",
3
- "version": "1.3.64",
3
+ "version": "1.3.66",
4
4
  "author": "ewagstaff <evanjwagstaff@gmail.com>",
5
5
  "dependencies": {
6
6
  "archieml": "^0.4.2",
@@ -10,6 +10,7 @@
10
10
  "htmlparser2": "4.1.0",
11
11
  "opn": "^6.0.0",
12
12
  "prop-types": "^15.8.1",
13
+ "react-transition-group": "^4.4.5",
13
14
  "write": "^2.0.0"
14
15
  }
15
16
  }
@@ -0,0 +1,62 @@
1
+ @import (less) '../values';
2
+
3
+ .container-stacked {
4
+ margin: 0 auto;
5
+ white-space: nowrap;
6
+ padding-bottom: calc(@xl*2/3);
7
+
8
+ @media @tablet {
9
+ padding-bottom: calc(100vw * (2/3));
10
+ }
11
+ }
12
+
13
+ .container-fullscreen {
14
+ padding-bottom: calc(100vh - 37px);
15
+ width: 100%;
16
+
17
+ @media @tablet {
18
+ margin: 0 auto;
19
+ white-space: nowrap;
20
+ padding-bottom: calc(100vw * (2/3));
21
+ }
22
+ }
23
+
24
+ .image-wrapper-stacked {
25
+ position: absolute;
26
+ width: 100%;
27
+ }
28
+
29
+ .image-wrapper-fullscreen {
30
+ position: absolute;
31
+ width: 100%;
32
+
33
+ @media @mobile {
34
+ margin: 0;
35
+ padding: 0;
36
+ height: auto;
37
+ }
38
+ }
39
+
40
+ /* enter animation */
41
+ .fade-enter {
42
+ opacity: 0;
43
+ }
44
+
45
+ .fade-enter.fade-enter-active {
46
+ opacity: 1;
47
+ transition: opacity 1500ms linear;
48
+ }
49
+
50
+ /* exit animation */
51
+ .fade-exit {
52
+ opacity: 1;
53
+ }
54
+
55
+ .fade-exit.fade-exit-active {
56
+ opacity: 0;
57
+ transition: opacity 2000ms linear;
58
+ }
59
+
60
+ .fade-exit-done {
61
+ opacity: 0;
62
+ }
@@ -1,49 +1,66 @@
1
1
  @import (less) "../variables.less";
2
2
 
3
- :root {
4
- --headerDek-vertical-offset: 0px;
5
- --headerDek-horizontal-offset: 0px;
3
+ :root {
4
+ --headerDek-vertical-offset: 0px;
5
+ --headerDek-horizontal-offset: 0px;
6
6
  }
7
7
 
8
8
  .topperContainerFullScreen {
9
- max-width: 100%;
10
- position: relative;
9
+ max-width: 100%;
10
+ position: relative;
11
+ }
12
+
13
+ .topperContainerSlideshowFullScreen {
14
+ max-width: 100%;
15
+ position: relative;
16
+ height: calc(100vh - 37px);
17
+
18
+ @media @tablet {
19
+ height: auto;
20
+ }
11
21
  }
12
22
 
13
23
  .imageFullScreen {
14
- top: 0 !important;
15
- width: 100%;
24
+ top: 0 !important;
25
+ width: 100%;
26
+
27
+ @media @mobile {
28
+ height: 100%;
29
+ }
16
30
  }
17
31
 
18
32
  .imageStacked {
19
- position: relative;
20
- overflow: hidden;
33
+ position: relative;
34
+ max-width: @xl;
21
35
 
22
- @media @mobile {
23
- width: 100%;
24
- }
36
+ @media @mobile {
37
+ width: 100%;
38
+ }
25
39
  }
26
40
 
27
41
  .headerDekStacked {
28
42
  margin-left: auto;
29
43
  margin-right: auto;
44
+
30
45
  @media (max-width: 960px) {
31
46
  margin-left: 0;
32
47
  margin-right: 0;
33
48
  }
34
49
  }
50
+
35
51
  .headerDekFullScreen {
36
- position: absolute;
37
- padding: @s24;
38
- width: @md;
39
- @media @tablet {
40
- width: @sm;
41
- position: static;
42
- transform: none;
43
- margin: 0;
44
- padding: 0;
45
- width: 100%;
46
- }
52
+ position: absolute;
53
+ padding: @s24;
54
+ width: @md;
55
+
56
+ @media @tablet {
57
+ width: @sm;
58
+ position: static;
59
+ transform: none;
60
+ margin: 0;
61
+ padding: 0;
62
+ width: 100%;
63
+ }
47
64
  }
48
65
 
49
66
  .hedFullScreen {
@@ -51,51 +68,55 @@
51
68
  }
52
69
 
53
70
  .deckFullScreen {
54
- margin-bottom: 0px;
71
+ margin-bottom: 0px;
55
72
  }
56
73
 
57
74
  .headerDekTop {
58
75
  top: 0%;
59
76
  margin-top: var(--headerDek-vertical-offset);
77
+
60
78
  @media @tablet {
61
- margin-top: 0px;
79
+ margin-top: 0px;
62
80
  }
63
81
  }
64
82
 
65
83
  .headerDekBottom {
66
84
  bottom: 0%;
67
85
  margin-bottom: var(--headerDek-vertical-offset);
86
+
68
87
  @media @tablet {
69
- margin-bottom: 0px;
88
+ margin-bottom: 0px;
70
89
  }
71
90
  }
72
91
 
73
92
  .headerDekLeft {
74
93
  left: 0%;
75
94
  margin-left: var(--headerDek-horizontal-offset);
95
+
76
96
  @media @tablet {
77
- margin-left: 0px;
97
+ margin-left: 0px;
78
98
  }
79
99
  }
80
100
 
81
101
  .headerDekRight {
82
102
  right: 0%;
83
103
  margin-right: var(--headerDek-horizontal-offset);
104
+
84
105
  @media @tablet {
85
- margin-right: 0px;
106
+ margin-right: 0px;
86
107
  }
87
108
  }
88
109
 
89
110
  .headerDekCenter {
90
- left: 50%;
111
+ left: 50%;
91
112
  transform: translate(-50%, 0%);
92
113
  margin-left: var(--headerDek-horizontal-offset);
93
114
 
94
- @media @tablet {
95
- transform: none;
96
- top: 0%;
97
- left: 0%;
98
- margin-left: 0px;
115
+ @media @tablet {
116
+ transform: none;
117
+ top: 0%;
118
+ left: 0%;
119
+ margin-left: 0px;
99
120
  }
100
121
  }
101
122
 
@@ -105,6 +126,7 @@
105
126
 
106
127
  .textAlignCenter {
107
128
  text-align: center;
129
+
108
130
  @media @tablet {
109
131
  text-align: left;
110
132
  }
@@ -113,6 +135,7 @@
113
135
  .whiteTextBlackBg {
114
136
  color: @white;
115
137
  background-color: rgba(0, 0, 0, 0.54);
138
+
116
139
  @media @tablet {
117
140
  color: @black;
118
141
  background-color: transparent;
@@ -124,15 +147,16 @@
124
147
  background-color: rgba(255, 255, 255, 0.54);
125
148
  }
126
149
 
127
- .hideWhenMobile {
128
- @media @mobile {
129
- display: none;
150
+ .hideWhenTablet {
151
+ @media @tablet {
152
+ display: none;
130
153
  }
131
154
  }
132
155
 
133
156
  .hideWhenDesktop {
134
157
  display: none;
135
- @media @mobile {
158
+
159
+ @media @tablet {
136
160
  display: block;
137
161
  padding-left: @s8;
138
162
  }
@@ -140,4 +164,10 @@
140
164
 
141
165
  .smallPaddingLeft {
142
166
  padding-left: @s8;
167
+ }
168
+
169
+ .smallPaddingLeftWhenTablet {
170
+ @media @tablet {
171
+ padding-left: @s8;
172
+ }
143
173
  }
@@ -1,10 +1,35 @@
1
1
  @import (less) '../values';
2
2
  @import (less) "../variables.less";
3
3
 
4
- :root {
4
+ :root {
5
5
  --img-bottom-padding-ratio: "56.25%";
6
6
  }
7
7
 
8
+ .c-force-aspect-ratio {
9
+ display: static;
10
+ width: @xl;
11
+ object-fit: cover;
12
+ height: calc(@xl*2/3);
13
+ margin: 0 auto;
14
+
15
+ @media @tablet {
16
+ height: calc(100vw*2/3);
17
+ }
18
+ }
19
+
20
+ .c-img-slideshow-fullscreen {
21
+ display: static;
22
+ width: 100%;
23
+ object-fit: cover;
24
+ height: calc(100vh - 37px);
25
+ margin: 0 auto;
26
+
27
+ @media @tablet {
28
+ width: @xl;
29
+ height: calc(100vw*2/3);
30
+ }
31
+ }
32
+
8
33
  .c-img {
9
34
  display: block;
10
35
  position: relative;
@@ -17,7 +42,9 @@
17
42
  .c-img-fullscreen {
18
43
  position: static;
19
44
  object-fit: cover;
45
+ width: 100%;
20
46
  height: calc(100vh - 37px);
47
+
21
48
  @media @tablet {
22
49
  height: auto;
23
50
  }
@@ -25,7 +52,8 @@
25
52
 
26
53
  .c-fig-hidden-when-desktop {
27
54
  display: none;
28
- @media @mobile {
55
+
56
+ @media @tablet {
29
57
  display: block;
30
58
  padding-left: @s8;
31
59
  }
@@ -94,6 +94,7 @@
94
94
  .pa-xl {padding: @s40;}
95
95
  .pa-xxl {padding: @s48;}
96
96
 
97
+ .mw-xs {max-width: @xs;}
97
98
  .mw-sm {max-width: @sm;}
98
99
  .mw-md {max-width: @md;}
99
100
  .mw-lg {max-width: @lg;}