sfc-utils 1.4.202 → 1.4.204

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 (93) hide show
  1. package/.playwright-mcp/console-2026-04-02T20-52-32-578Z.log +994 -0
  2. package/.playwright-mcp/page-2026-04-02T20-52-43-138Z.yml +13584 -0
  3. package/.playwright-mcp/page-2026-04-02T20-52-52-183Z.png +0 -0
  4. package/components/geocoder.mjs +1 -0
  5. package/components/helpers/utilfunctions.mjs +17 -24
  6. package/components/layout/layouthelmet.mjs +4 -0
  7. package/footer.js +54 -0
  8. package/index.js +4 -0
  9. package/package.json +1 -1
  10. package/settings.js +2 -2
  11. package/example/.prettierrc +0 -5
  12. package/example/README.md +0 -8
  13. package/example/gatsby-config.js +0 -137
  14. package/example/gatsby-node.js +0 -66
  15. package/example/package-lock.json +0 -31884
  16. package/example/package.json +0 -71
  17. package/example/project-config.json +0 -38
  18. package/example/src/components/layout.js +0 -96
  19. package/example/src/components/sfc/ad.js +0 -47
  20. package/example/src/components/sfc/ai2html/ai2html_template.ai +5 -1368
  21. package/example/src/components/sfc/button.js +0 -40
  22. package/example/src/components/sfc/byline.js +0 -42
  23. package/example/src/components/sfc/component-helpers/customhooks.js +0 -17
  24. package/example/src/components/sfc/component-helpers/datehelpers.js +0 -55
  25. package/example/src/components/sfc/component-helpers/newsletterhelpers.js +0 -89
  26. package/example/src/components/sfc/component-helpers/requesthelpers.js +0 -7
  27. package/example/src/components/sfc/component-helpers/scrolldownhelpers.js +0 -11
  28. package/example/src/components/sfc/component-helpers/utilfunctions.js +0 -68
  29. package/example/src/components/sfc/creditline.js +0 -35
  30. package/example/src/components/sfc/credits.js +0 -17
  31. package/example/src/components/sfc/creditssection.js +0 -49
  32. package/example/src/components/sfc/dropcap.js +0 -15
  33. package/example/src/components/sfc/footer.js +0 -36
  34. package/example/src/components/sfc/geocoder.js +0 -148
  35. package/example/src/components/sfc/misccredit.js +0 -17
  36. package/example/src/components/sfc/navtop.js +0 -121
  37. package/example/src/components/sfc/newsletter.js +0 -157
  38. package/example/src/components/sfc/relatedlink.js +0 -23
  39. package/example/src/components/sfc/relatedrow.js +0 -23
  40. package/example/src/components/sfc/relatedsection.js +0 -27
  41. package/example/src/components/sfc/safelink.js +0 -86
  42. package/example/src/components/sfc/scrolldown.js +0 -22
  43. package/example/src/components/sfc/sharebuttons.js +0 -93
  44. package/example/src/components/sfc/topper.js +0 -88
  45. package/example/src/components/sfc/video.js +0 -74
  46. package/example/src/components/sfc/wcmimage.js +0 -131
  47. package/example/src/data/sfc/images/react.gif +0 -0
  48. package/example/src/data/sfc/related_links.json +0 -17
  49. package/example/src/html.js +0 -41
  50. package/example/src/pages/index.js +0 -166
  51. package/example/src/styles/credittooltip.less +0 -55
  52. package/example/src/styles/footer.less +0 -378
  53. package/example/src/styles/modules/ad.module.less +0 -21
  54. package/example/src/styles/modules/ai2html.module.less +0 -19
  55. package/example/src/styles/modules/button.module.less +0 -94
  56. package/example/src/styles/modules/byline.module.less +0 -11
  57. package/example/src/styles/modules/creditline.module.less +0 -12
  58. package/example/src/styles/modules/credits.module.less +0 -7
  59. package/example/src/styles/modules/creditssection.module.less +0 -17
  60. package/example/src/styles/modules/dropcap.module.less +0 -18
  61. package/example/src/styles/modules/geocoder.module.less +0 -79
  62. package/example/src/styles/modules/newsletter.module.less +0 -147
  63. package/example/src/styles/modules/relatedlink.module.less +0 -28
  64. package/example/src/styles/modules/relatedrow.module.less +0 -8
  65. package/example/src/styles/modules/relatedsection.module.less +0 -19
  66. package/example/src/styles/modules/scrolldown.module.less +0 -31
  67. package/example/src/styles/modules/share.module.less +0 -22
  68. package/example/src/styles/modules/topper.module.less +0 -63
  69. package/example/src/styles/modules/video.module.less +0 -27
  70. package/example/src/styles/modules/wcmimage.module.less +0 -20
  71. package/example/src/styles/nav.less +0 -187
  72. package/example/src/styles/old css/defaults.less +0 -99
  73. package/example/src/styles/old css/footer.less +0 -345
  74. package/example/src/styles/old css/nav.less +0 -187
  75. package/example/src/styles/old css/project.less +0 -1
  76. package/example/src/styles/old css/reset.css +0 -95
  77. package/example/src/styles/old css/seed.less +0 -7
  78. package/example/src/styles/old css/typography.css +0 -168
  79. package/example/src/styles/old css/values.less +0 -74
  80. package/example/src/styles/project.less +0 -1
  81. package/example/src/styles/reset.css +0 -97
  82. package/example/src/styles/seed.less +0 -6
  83. package/example/src/styles/values.less +0 -203
  84. package/example/src/styles/variables.less +0 -142
  85. package/example/static/manifest.webmanifest +0 -1
  86. package/example/tasks/create-c2p-sheet.js +0 -6
  87. package/example/tasks/deploy-addon.py +0 -14
  88. package/example/tasks/google-docs.js +0 -16
  89. package/example/tasks/google-sheets.js +0 -17
  90. package/example/tasks/node-helpers.js +0 -81
  91. package/example/tasks/post-build.sh +0 -7
  92. package/example/tasks/pre-build.sh +0 -18
  93. package/example/tempsettings.js +0 -28
@@ -45,6 +45,7 @@ const Geocoder = ({
45
45
  case "Houston":
46
46
  case "SanAntonio":
47
47
  case "Austin":
48
+ case "Dallas":
48
49
  filterRegion = "Texas";
49
50
  break;
50
51
  case "Albany":
@@ -200,40 +200,33 @@ function trackEvent(
200
200
  event = "hnp_impression";
201
201
  }
202
202
 
203
+ const baseEvent = {
204
+ event: event, //REQUIRED; Fixed value
205
+ element_name: elementName, //REQUIRED; One of a list of tags/types of elements on the page (e.g. Button, Map, Tooltip, ToggleButton, Dropdown). TO DO: create a consistent list of this
206
+ element_content: elementContent, //REQUIRED; One of a list of subtypes of element types (e.g. Button) on the page (e.g. Geocoder, Searchbar, Prev/Next). TO DO: create a consistent list of this, maybe
207
+ element_variant: elementVariant, //REQUIRED; Template type (e.g. custom-repo-name|gatsby) (top-list|plat)
208
+ element_text: elementText, //REQUIRED; What was the actual text or alt-text of the thing that was clicked (InnerHTML or id specific to that element)
209
+ component_type: null, //OPTIONAL; If BC components uses Storybook components: Organism or molecule from storybook (whatever the highest level component from storybook that the clicked on item belongs to)
210
+ component_subtype: null, //OPTIONAL; If BC components uses Storybook components: Variant of the component_type from storybook
211
+ component_detail: null, //OPTIONAL; If BC components uses Storybook components: WCM TITLE|Position|Atom from storybook. This pipe-delimited structure is required. When values are not available for a given position, leave the position blank so the order of information doesn't change. e.g. something|| or something||something_else
212
+ zone: null, // OPTIONAL; For WCM components. The WCM zone the component was displayed in.
213
+ link_url: linkUrl, //REQUIRED; What is the slug of the project?
214
+ outbound: false, //REQUIRED; Boolean indicating whether the link that was clicked took the user to a different domain.
215
+ source_system: "devhub", //REQUIRED; What platform powered the element? One of cookie, blueconic, realm, castle, devhub, treg, legacy obits, sailthru, casper, wordpress, hnp-jwplayer, event_data_service (other options required discussion with BI/DE)
216
+ };
217
+
203
218
  if (window.dataLayer) {
204
219
  // this is NOT an embed, so push to the dataLayer
205
220
  const urlHash = window.HDN.dataLayer?.visit?.urlHash;
206
221
 
207
222
  window.dataLayer.push({
208
- event: event, //REQUIRED; Fixed value
209
- element_name: elementName, //REQUIRED; One of a list of tags/types of elements on the page (e.g. Button, Map, Tooltip, ToggleButton, Dropdown). TO DO: create a consistent list of this
210
- element_content: elementContent, //REQUIRED; One of a list of subtypes of element types (e.g. Button) on the page (e.g. Geocoder, Searchbar, Prev/Next). TO DO: create a consistent list of this, maybe
211
- element_variant: elementVariant, //REQUIRED; Template type (e.g. custom-repo-name|gatsby) (top-list|plat)
212
- element_text: elementText, //REQUIRED; What was the actual text or alt-text of the thing that was clicked (InnerHTML or id specific to that element)
213
- component_type: null, //OPTIONAL; If BC components uses Storybook components: Organism or molecule from storybook (whatever the highest level component from storybook that the clicked on item belongs to)
214
- component_subtype: null, //OPTIONAL; If BC components uses Storybook components: Variant of the component_type from storybook
215
- component_detail: null, //OPTIONAL; If BC components uses Storybook components: WCM TITLE|Position|Atom from storybook. This pipe-delimited structure is required. When values are not available for a given position, leave the position blank so the order of information doesn't change. e.g. something|| or something||something_else
216
- zone: null, // OPTIONAL; For WCM components. The WCM zone the component was displayed in.
217
- link_url: linkUrl, //REQUIRED; What is the slug of the project?
223
+ ...baseEvent,
218
224
  url_hash: urlHash, // REQUIRED;
219
- outbound: false, //REQUIRED; Boolean indicating whether the link that was clicked took the user to a different domain.
220
- source_system: "devhub", //REQUIRED; What platform powered the element? One of cookie, blueconic, realm, castle, devhub, treg, legacy obits, sailthru, casper, wordpress, hnp-jwplayer, event_data_service (other options required discussion with BI/DE)
221
225
  });
222
226
  } else {
223
227
  // this IS an embed, so use this special logic
224
228
  var embed_event = {
225
- event: event, //REQUIRED; Fixed value
226
- element_name: elementName, //REQUIRED; One of a list of tags/types of elements on the page (e.g. Button, Map, Tooltip, ToggleButton, Dropdown). TO DO: create a consistent list of this
227
- element_content: elementContent, //REQUIRED; One of a list of subtypes of element types (e.g. Button) on the page (e.g. Geocoder, Searchbar, Prev/Next). TO DO: create a consistent list of this, maybe
228
- element_variant: elementVariant, //REQUIRED; Template type (e.g. custom-repo-name|gatsby) (top-list|plat)
229
- element_text: elementText, //REQUIRED; What was the actual text or alt-text of the thing that was clicked (InnerHTML or id specific to that element)
230
- component_type: null, //OPTIONAL; If BC components uses Storybook components: Organism or molecule from storybook (whatever the highest level component from storybook that the clicked on item belongs to)
231
- component_subtype: null, //OPTIONAL; If BC components uses Storybook components: Variant of the component_type from storybook
232
- component_detail: null, //OPTIONAL; If BC components uses Storybook components: WCM TITLE|Position|Atom from storybook. This pipe-delimited structure is required. When values are not available for a given position, leave the position blank so the order of information doesn't change. e.g. something|| or something||something_else
233
- zone: null, // OPTIONAL; For WCM components. The WCM zone the component was displayed in.
234
- link_url: linkUrl, //REQUIRED; What is the slug of the project?
235
- outbound: false, //REQUIRED; Boolean indicating whether the link that was clicked took the user to a different domain.
236
- source_system: "devhub", //REQUIRED; What platform powered the element? One of cookie, blueconic, realm, castle, devhub, treg, legacy obits, sailthru, casper, wordpress, hnp-jwplayer, event_data_service (other options required discussion with BI/DE)
229
+ ...baseEvent,
237
230
  iframe_event: true,
238
231
  };
239
232
 
@@ -126,6 +126,10 @@ const LayoutHelmet = ({
126
126
  favHref =
127
127
  "https://www.statesman.com/sites/statesman/apple-touch-icon-196x196.png";
128
128
  }
129
+ else if (MARKET_KEY === "Dallas") {
130
+ favHref =
131
+ "https://www.dallasnews.com/sites/dallasnews/apple-touch-icon-196x196.png";
132
+ }
129
133
 
130
134
  // Set section with fallback
131
135
  let articleSection = "Local";
package/footer.js CHANGED
@@ -786,6 +786,60 @@ let getFooter = function (meta, forceColor) {
786
786
  },
787
787
  ],
788
788
  },
789
+ Dallas: {
790
+ About: [
791
+ {
792
+ text: 'Our Company',
793
+ link: 'https://www.hearst.com/the-dallas-morning-news',
794
+ },
795
+ {
796
+ text: 'Privacy',
797
+ link: '/privacy/',
798
+ },
799
+ {
800
+ text: 'DAA Industry Opt-Out',
801
+ link: '/privacy/#daaindustryoptout',
802
+ },
803
+ {
804
+ text: 'Terms of Use',
805
+ link: '/terms/',
806
+ },
807
+ {
808
+ text: 'Advertising',
809
+ link: 'https://mediumgiant.co/advertise-with-the-dallas-morning-news/',
810
+ },
811
+ {
812
+ text: 'Careers',
813
+ link: '/careers',
814
+ },
815
+ ],
816
+ Contact: [
817
+ {
818
+ text: 'Archives',
819
+ link: '/archive/search/subscriber/',
820
+ },
821
+ {
822
+ text: 'Customer Service',
823
+ link: '/help/',
824
+ },
825
+ {
826
+ text: 'Frequently Asked Questions',
827
+ link: '/subscriberfaqs/',
828
+ },
829
+ {
830
+ text: 'Newsroom Contacts',
831
+ link: '/contact/staff/',
832
+ },
833
+ {
834
+ text: 'Our Use of AI',
835
+ link: '/ai_use/',
836
+ },
837
+ {
838
+ text: 'Ethics Policy',
839
+ link: '/standards/',
840
+ },
841
+ ],
842
+ },
789
843
  TK: {
790
844
  About: [
791
845
  {
package/index.js CHANGED
@@ -163,6 +163,10 @@ let blendHDN = function (meta) {
163
163
  HDN.dataLayer.source.authorTitle = "Austin American-Statesman Staff";
164
164
  HDN.dataLayer.source.originalSourceSite = "statesman";
165
165
  break;
166
+ case "Dallas":
167
+ HDN.dataLayer.source.authorTitle = "Dallas Morning News Staff";
168
+ HDN.dataLayer.source.originalSourceSite = "dallasnews";
169
+ break;
166
170
  }
167
171
 
168
172
  // HDN.dataLayer object for sharing information
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sfc-utils",
3
- "version": "1.4.202",
3
+ "version": "1.4.204",
4
4
  "author": "ewagstaff <evanjwagstaff@gmail.com>",
5
5
  "dependencies": {
6
6
  "archieml": "^0.4.2",
package/settings.js CHANGED
@@ -32,8 +32,8 @@ let getSettings = function () {
32
32
  try {
33
33
  try {
34
34
  [storySettings] = require("../../src/data/story_settings.sheet.json");
35
- // Uncomment line below and comment out line above if testing from example folder in utils
36
- // [storySettings] = require("./example/src/data/story_settings.sheet.json")
35
+ // Uncomment line below and comment out line above if testing against a local story settings fixture
36
+ // [storySettings] = require("./src/data/story_settings.sheet.json")
37
37
 
38
38
  // If we got story_settings, try structuring the AUTHORS object
39
39
  let authorNames = [];
@@ -1,5 +0,0 @@
1
- {
2
- "semi": false,
3
- "singleQuote": true,
4
- "trailingComma": "es5"
5
- }
package/example/README.md DELETED
@@ -1,8 +0,0 @@
1
- # {%= app_slug %}
2
-
3
- {%= github_desc %}
4
-
5
- View the live project: [{%= project_url %}]({%= project_url %})
6
-
7
- This project was built with the SFC Newsapp template. For instructions on how to use this template, refer to [the template README](https://github.com/sfchronicle/gatsby-newsapp))
8
-
@@ -1,137 +0,0 @@
1
- // Add SFC utils
2
- const { getBrands3 } = require('../index')
3
- const { getSettings } = require('./tempsettings')
4
- const { DateTime } = require('luxon')
5
-
6
- let settings = getSettings()
7
-
8
- let marketKeyArray = [
9
- { markets: ['SFC'], zone: 'America/Los_Angeles' },
10
- {
11
- markets: ['Houston', 'SanAntonio', 'Texcom', 'Austin'],
12
- zone: 'America/Chicago',
13
- },
14
- { markets: ['Albany', 'CT', 'Midcom'], zone: 'America/New_York' },
15
- ]
16
-
17
- let currentZone
18
- // Find the current market in the array
19
- for (let region in marketKeyArray) {
20
- let thisRegion = marketKeyArray[region]
21
- if (thisRegion.markets.includes(settings.PROJECT.MARKET_KEY)) {
22
- currentZone = thisRegion.zone
23
- }
24
- }
25
- // If we don't have a match, that means we have an invalid market key
26
- if (!currentZone) {
27
- console.error(
28
- 'Invalid or undefined MARKET_KEY! See the _key_explainer in project-config to see valid values.'
29
- )
30
- process.exit(1)
31
- }
32
-
33
- // Create computer pub and mod dates
34
- const dt = DateTime.fromFormat(settings.PROJECT.DATE, 'MMMM d, y h:mm a', {
35
- zone: currentZone,
36
- })
37
- // Convert date to computer-readable time
38
- const computerPubDate = dt.toISO()
39
- settings.PROJECT.ISO_PUBDATE = computerPubDate
40
-
41
- // If MOD_DATE does not exist, set var to pubdate
42
- let computerModDate = ''
43
- if (
44
- typeof settings.PROJECT.MOD_DATE !== 'undefined' &&
45
- settings.PROJECT.MOD_DATE
46
- ) {
47
- const dt2 = DateTime.fromFormat(
48
- settings.PROJECT.MOD_DATE,
49
- 'MMMM d, y h:mm a',
50
- { zone: currentZone }
51
- )
52
- computerModDate = dt2.toISO()
53
- } else {
54
- // Fallback to creation date
55
- computerModDate = computerPubDate
56
- }
57
- settings.PROJECT.ISO_MODDATE = computerModDate
58
-
59
- //Set get the current env var
60
- const currentEnv = process.env.GATSBY_DEPLOY_ENV
61
- console.log('Current environment: ' + currentEnv)
62
-
63
- // Handle test prefix
64
- // TODO: Once we embrace the new URL, we can delete this check and hardcode /projects
65
- let projectsPrefix = ''
66
- if (settings.PROJECT.SUBFOLDER.toString().indexOf('projects/') === 0) {
67
- projectsPrefix = '/projects'
68
- }
69
- // Set the path prefix for the given deploy (ignored for dev)
70
- let pathPrefix = '/projects/test-proj/' + settings.PROJECT.SLUG
71
- if (currentEnv === 'development') {
72
- pathPrefix = '/'
73
- }
74
- if (currentEnv === 'app') {
75
- pathPrefix = projectsPrefix + '/app/' + settings.PROJECT.SLUG
76
- }
77
- if (currentEnv === 'production') {
78
- pathPrefix =
79
- '/' +
80
- settings.PROJECT.SUBFOLDER +
81
- settings.PROJECT.OPT_SLASH +
82
- settings.PROJECT.SLUG
83
- }
84
-
85
- let plugins = [
86
- 'gatsby-plugin-react-helmet',
87
- 'gatsby-transformer-json',
88
- {
89
- resolve: 'gatsby-plugin-less',
90
- options: {
91
- lessOptions: {
92
- modifyVars: getBrands3(settings.PROJECT.MARKET_KEY).styles,
93
- },
94
- },
95
- },
96
- {
97
- resolve: 'gatsby-plugin-html-attributes',
98
- options: {
99
- lang: 'en',
100
- },
101
- },
102
- {
103
- resolve: `gatsby-source-filesystem`,
104
- options: {
105
- name: `projectData`,
106
- path: `${__dirname}/src/data/`,
107
- },
108
- },
109
- {
110
- resolve: 'gatsby-plugin-webpack-bundle-analyser-v2',
111
- options: {
112
- production: true,
113
- disable: !process.env.ANALYZE_BUNDLE_SIZE,
114
- generateStatsFile: true,
115
- analyzerMode: 'static',
116
- },
117
- },
118
- // this (optional) plugin enables Progressive Web App + Offline functionality
119
- // To learn more, visit: https://gatsby.app/offline
120
- // 'gatsby-plugin-offline',
121
- ]
122
-
123
- // Enable preact for the prod build
124
- if (currentEnv !== 'development') {
125
- plugins.push('gatsby-plugin-preact')
126
- }
127
-
128
- // TK builds get weird redirect loops with htaccess plugin, so don't use it
129
- if (settings.PROJECT.MARKET_KEY !== 'TK') {
130
- plugins.push('gatsby-plugin-htaccess')
131
- }
132
-
133
- module.exports = {
134
- siteMetadata: settings,
135
- pathPrefix: pathPrefix,
136
- plugins: plugins,
137
- }
@@ -1,66 +0,0 @@
1
- /**
2
- * Implement Gatsby's Node APIs in this file.
3
- *
4
- * See: https://www.gatsbyjs.org/docs/node-apis/
5
- */
6
-
7
- var { requestImage } = require("./tasks/node-helpers");
8
- let topperData = require("./src/data/topper2_settings.sheet.json");
9
-
10
- // Import all the WCM photos you'd like to use in this project
11
- // NOTE: Leave this as an empty array if you aren't importing any WCM photos, but you won't be able to use the WCMImage component
12
- const wcmPhotos = ["20374215"]
13
-
14
- const addValidWcmId = (numStr, wcmPhotos) => {
15
- let isNum = /^\d+$/.test(numStr.trim())
16
- if (isNum && !wcmPhotos.includes(numStr.trim())) wcmPhotos.push((numStr.trim()));
17
- }
18
-
19
- // Add topper image(s) to wcmPhotos list
20
- if (topperData[0].Image) {
21
- let numStr = (topperData[0].Image).toString();
22
-
23
- if (numStr.includes(";")) {
24
- let numList = numStr.split(";");
25
- for (var num of numList) {
26
- addValidWcmId(num, wcmPhotos);
27
- }
28
- } else {
29
- addValidWcmId(numStr, wcmPhotos);
30
- }
31
- }
32
-
33
-
34
- // Create nodes so GraphQL can access
35
- exports.sourceNodes = async ({
36
- actions,
37
- createNodeId,
38
- createContentDigest,
39
- }) => {
40
- const { createNode } = actions
41
-
42
- // Request and push photo data into an array
43
- const photoData = [];
44
- wcmPhotos.forEach((url) => {
45
- photoData.push(requestImage(url))
46
- })
47
-
48
- // Take the ratios/ids turn them into graphql nodes
49
- await Promise.all(photoData).then((values) => {
50
- values.forEach((photo) => {
51
- const type = "wcmPhotos";
52
- createNode({
53
- photo,
54
- id: createNodeId(`${type}${photo.wcmid}`),
55
- parent: null,
56
- children: [],
57
- internal: {
58
- contentDigest: createContentDigest(photo),
59
- type,
60
- },
61
- })
62
- })
63
- return
64
- })
65
- return
66
- }