create-sitecore-jss 22.2.0-canary.11 → 22.2.0-canary.13

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.
@@ -1,12 +1,12 @@
1
1
  import { RouteData, LayoutServiceContextData } from '@sitecore-jss/sitecore-jss-angular';
2
2
  import { LayoutServiceError } from './layout/jss-layout.service';
3
3
 
4
- export class JssState<Fields = Record<string, unknown>> {
4
+ export class JssState {
5
5
  language: string;
6
6
  serverRoute: string;
7
7
  routeFetchError?: LayoutServiceError;
8
8
  sitecore?: LayoutServiceContextData & {
9
- route: RouteData<Fields>;
9
+ route: RouteData | null;
10
10
  };
11
11
  viewBag: { [key: string]: unknown };
12
12
  }
@@ -11,6 +11,7 @@ import { JssTranslationClientLoaderService } from './i18n/jss-translation-client
11
11
  import { JssTranslationLoaderService } from './i18n/jss-translation-loader.service';
12
12
  import { GraphQLModule } from './jss-graphql.module';
13
13
  import { JssMetaService } from './jss-meta.service';
14
+ import { JssLinkService } from './jss-link.service';
14
15
 
15
16
  @NgModule({
16
17
  imports: [
@@ -32,6 +33,7 @@ import { JssMetaService } from './jss-meta.service';
32
33
  JssContextService,
33
34
  JssLayoutService,
34
35
  JssMetaService,
36
+ JssLinkService,
35
37
  // IMPORTANT: you must set the base href with this token, not a <base> tag in the HTML.
36
38
  // the Sitecore Experience Editor will not work correctly when a base tag is used.
37
39
  { provide: APP_BASE_HREF, useValue: '/' },
@@ -9,12 +9,12 @@ import { JssMetaService } from '../../jss-meta.service';
9
9
  enum LayoutState {
10
10
  Layout,
11
11
  NotFound,
12
- Error
12
+ Error,
13
13
  }
14
14
 
15
15
  interface RouteFields {
16
16
  [name: string]: unknown;
17
- pageTitle: Field<string>;
17
+ pageTitle?: Field<string>;
18
18
  }
19
19
 
20
20
  @Component({
@@ -28,14 +28,11 @@ export class LayoutComponent implements OnInit, OnDestroy {
28
28
  subscription: Subscription;
29
29
  errorContextData: LayoutServiceContextData;
30
30
 
31
- constructor(
32
- private activatedRoute: ActivatedRoute,
33
- private readonly meta: JssMetaService,
34
- ) { }
31
+ constructor(private activatedRoute: ActivatedRoute, private readonly meta: JssMetaService) {}
35
32
 
36
33
  ngOnInit() {
37
34
  // route data is populated by the JssRouteResolver
38
- this.subscription = this.activatedRoute.data.subscribe((data: { jssState: JssState<RouteFields> }) => {
35
+ this.subscription = this.activatedRoute.data.subscribe((data: { jssState: JssState }) => {
39
36
  if (!data.jssState) {
40
37
  this.state = LayoutState.NotFound;
41
38
  return;
@@ -48,13 +45,17 @@ export class LayoutComponent implements OnInit, OnDestroy {
48
45
  }
49
46
 
50
47
  if (data.jssState.routeFetchError) {
51
- if (data.jssState.routeFetchError.status >= 400 && data.jssState.routeFetchError.status < 500) {
48
+ if (
49
+ data.jssState.routeFetchError.status >= 400 &&
50
+ data.jssState.routeFetchError.status < 500
51
+ ) {
52
52
  this.state = LayoutState.NotFound;
53
53
  } else {
54
54
  this.state = LayoutState.Error;
55
55
  }
56
56
 
57
- this.errorContextData = data.jssState.routeFetchError.data && data.jssState.routeFetchError.data.sitecore;
57
+ this.errorContextData =
58
+ data.jssState.routeFetchError.data && data.jssState.routeFetchError.data.sitecore;
58
59
  }
59
60
  });
60
61
  }
@@ -4,11 +4,7 @@ import { HTMLLink } from '@sitecore-jss/sitecore-jss-angular';
4
4
 
5
5
  @Injectable()
6
6
  export class JssLinkService {
7
- document: Document;
8
-
9
- constructor() {
10
- this.document = Inject(DOCUMENT);
11
- }
7
+ constructor(@Inject(DOCUMENT) private document: Document) {}
12
8
 
13
9
  /**
14
10
  * Adds link element in the document head.
@@ -19,6 +15,11 @@ export class JssLinkService {
19
15
  return;
20
16
  }
21
17
 
18
+ // Check if a link with the same rel and href already exists
19
+ if (this.isDuplicateLink(headLink)) {
20
+ return;
21
+ }
22
+
22
23
  this.createLink(headLink);
23
24
  }
24
25
 
@@ -39,13 +40,14 @@ export class JssLinkService {
39
40
  }
40
41
 
41
42
  /**
42
- * Removes all link elements that match the specified rel attribute.
43
- * @param rel - The rel attribute of the links to be removed.
43
+ * Checks for an existing link element with the same rel and href attributes.
44
+ * @param headLink - An HTMLLink object to be checked.
45
+ * @returns {boolean} - True if a matching link exists, false otherwise.
44
46
  */
45
- removeLinksByRel(rel: string) {
46
- const links = this.document.head.querySelectorAll(`link[rel="${rel}"]`);
47
- links.forEach((link) => {
48
- this.document.head.removeChild(link);
49
- });
47
+ private isDuplicateLink(headLink: HTMLLink): boolean {
48
+ const existingLink = this.document.head.querySelector(
49
+ `link[rel='${headLink.rel}'][href='${headLink.href}']`
50
+ );
51
+ return !!existingLink;
50
52
  }
51
53
  }
@@ -25,7 +25,7 @@
25
25
  <sc-placeholder
26
26
  name="headless-footer"
27
27
  [rendering]="route"
28
- (loaded)="onMainPlaceholderLoaded($event)"
28
+ (loaded)="onPlaceholderLoaded($event)"
29
29
  ></sc-placeholder>
30
30
  </div>
31
31
  </footer>
@@ -21,7 +21,7 @@ enum LayoutState {
21
21
 
22
22
  interface RouteFields {
23
23
  [name: string]: unknown;
24
- pageTitle: Field<string>;
24
+ pageTitle?: Field<string>;
25
25
  }
26
26
 
27
27
  @Component({
@@ -44,50 +44,45 @@ export class LayoutComponent implements OnInit, OnDestroy {
44
44
 
45
45
  ngOnInit() {
46
46
  // route data is populated by the JssRouteResolver
47
- this.subscription = this.activatedRoute.data.subscribe(
48
- (data: { jssState: JssState<RouteFields> }) => {
49
- if (!data.jssState) {
50
- this.state = LayoutState.NotFound;
51
- return;
52
- }
53
-
54
- if (data.jssState.sitecore && data.jssState.sitecore.route) {
55
- this.route = data.jssState.sitecore.route;
56
- this.setMetadata(this.route.fields);
57
- this.state = LayoutState.Layout;
58
- this.mainClassPageEditing = data.jssState.sitecore.context.pageEditing
59
- ? 'editing-mode'
60
- : 'prod-mode';
47
+ this.subscription = this.activatedRoute.data.subscribe((data: { jssState: JssState }) => {
48
+ if (!data.jssState) {
49
+ this.state = LayoutState.NotFound;
50
+ return;
51
+ }
61
52
 
62
- const contentStyles = getContentStylesheetLink(
63
- { sitecore: data.jssState.sitecore },
64
- env.sitecoreEdgeContextId,
65
- env.sitecoreEdgeUrl
66
- );
53
+ if (data.jssState.sitecore && data.jssState.sitecore.route) {
54
+ this.route = data.jssState.sitecore.route;
55
+ this.setMetadata(this.route.fields);
56
+ this.state = LayoutState.Layout;
57
+ this.mainClassPageEditing = data.jssState.sitecore.context.pageEditing
58
+ ? 'editing-mode'
59
+ : 'prod-mode';
67
60
 
68
- // Clear existing stylesheets
69
- this.linkService.removeLinksByRel('stylesheet');
61
+ const contentStyles = getContentStylesheetLink(
62
+ { sitecore: data.jssState.sitecore },
63
+ env.sitecoreEdgeContextId,
64
+ env.sitecoreEdgeUrl
65
+ );
70
66
 
71
- if (contentStyles) {
72
- this.linkService.addHeadLinks(contentStyles);
73
- }
67
+ if (contentStyles) {
68
+ this.linkService.addHeadLinks(contentStyles);
74
69
  }
70
+ }
75
71
 
76
- if (data.jssState.routeFetchError) {
77
- if (
78
- data.jssState.routeFetchError.status >= 400 &&
79
- data.jssState.routeFetchError.status < 500
80
- ) {
81
- this.state = LayoutState.NotFound;
82
- } else {
83
- this.state = LayoutState.Error;
84
- }
85
-
86
- this.errorContextData =
87
- data.jssState.routeFetchError.data && data.jssState.routeFetchError.data.sitecore;
72
+ if (data.jssState.routeFetchError) {
73
+ if (
74
+ data.jssState.routeFetchError.status >= 400 &&
75
+ data.jssState.routeFetchError.status < 500
76
+ ) {
77
+ this.state = LayoutState.NotFound;
78
+ } else {
79
+ this.state = LayoutState.Error;
88
80
  }
81
+
82
+ this.errorContextData =
83
+ data.jssState.routeFetchError.data && data.jssState.routeFetchError.data.sitecore;
89
84
  }
90
- );
85
+ });
91
86
  }
92
87
 
93
88
  ngOnDestroy() {
@@ -102,7 +97,7 @@ export class LayoutComponent implements OnInit, OnDestroy {
102
97
  }
103
98
  }
104
99
 
105
- onMainPlaceholderLoaded(_placeholderName: string) {
100
+ onPlaceholderLoaded(_placeholderName: string) {
106
101
  // you may optionally hook to the loaded event for a placeholder,
107
102
  // which can be useful for analytics and other DOM-based things that need to know when a placeholder's content is available.
108
103
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-sitecore-jss",
3
- "version": "22.2.0-canary.11",
3
+ "version": "22.2.0-canary.13",
4
4
  "description": "Sitecore JSS initializer",
5
5
  "bin": "./dist/index.js",
6
6
  "scripts": {
@@ -63,5 +63,5 @@
63
63
  "ts-node": "^10.9.1",
64
64
  "typescript": "~4.9.5"
65
65
  },
66
- "gitHead": "f4cca11e7c8662590ae43f3100065f0adb1728c5"
66
+ "gitHead": "072f7769baf7c74a7809458c5b51db4d1681f0fa"
67
67
  }