base-js-sw 1.0.2 → 1.0.3

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.
@@ -0,0 +1,36 @@
1
+ # This workflow will run tests using node and then publish a package to GitHub Packages when a release is created
2
+ # For more information see: https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages
3
+
4
+ name: Node.js Package
5
+
6
+ on:
7
+ release:
8
+ types: [created]
9
+
10
+ jobs:
11
+ build:
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+ - uses: actions/setup-node@v4
16
+ with:
17
+ node-version: 20
18
+ - run: npm ci
19
+ - run: npm test
20
+
21
+ publish-gpr:
22
+ needs: build
23
+ runs-on: ubuntu-latest
24
+ permissions:
25
+ contents: read
26
+ packages: write
27
+ steps:
28
+ - uses: actions/checkout@v4
29
+ - uses: actions/setup-node@v4
30
+ with:
31
+ node-version: 20
32
+ registry-url: https://npm.pkg.github.com/
33
+ - run: npm ci
34
+ - run: npm publish
35
+ env:
36
+ NODE_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}
@@ -0,0 +1,33 @@
1
+ # This workflow will run tests using node and then publish a package to GitHub Packages when a release is created
2
+ # For more information see: https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages
3
+
4
+ name: Node.js Package
5
+
6
+ on:
7
+ release:
8
+ types: [created]
9
+
10
+ jobs:
11
+ build:
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+ - uses: actions/setup-node@v4
16
+ with:
17
+ node-version: 20
18
+ - run: npm ci
19
+ - run: npm test
20
+
21
+ publish-npm:
22
+ needs: build
23
+ runs-on: ubuntu-latest
24
+ steps:
25
+ - uses: actions/checkout@v4
26
+ - uses: actions/setup-node@v4
27
+ with:
28
+ node-version: 20
29
+ registry-url: https://registry.npmjs.org/
30
+ - run: npm ci
31
+ - run: npm publish
32
+ env:
33
+ NODE_AUTH_TOKEN: ${{secrets.npm_token}}
@@ -10,41 +10,64 @@ import { MediaUpload, MediaUploadCheck } from '@wordpress/blockEditor';
10
10
  import { PanelBody, Button } from '@wordpress/components';
11
11
  import { __experimentalAlignmentMatrixControl as AlignmentMatrixControl } from '@wordpress/components';
12
12
  const { siteDomain } = themeVars; // vars passed from enqueue_backend.php
13
-
14
- export const ImagePicker = ({ setAttributes, imageObject = {}, extraClass, imageRef = 'imageObject', buttonText = 'Select image', showCrop = true }) => {
13
+ export const ImagePicker = ({
14
+ setAttributes,
15
+ imageObject = {},
16
+ extraClass,
17
+ imageRef = 'imageObject',
18
+ buttonText = 'Select image',
19
+ showCrop = true
20
+ }) => {
15
21
  let componentClass = 'component-image-picker';
16
22
 
17
23
  let imageOptionsString = 'images/width=250,height=150,crop=0';
18
24
  let resizedImageUrl = '';
19
25
 
20
- if(imageObject.hasOwnProperty('url') && imageObject.url !== ''){
21
- if(imageObject.url.endsWith('.svg')) {
22
- resizedImageUrl = imageObject.url;
26
+ // Determine if image is from current site domain
27
+ let isExternalImage = false;
28
+
29
+ if (imageObject.hasOwnProperty('url') && imageObject.url !== '') {
30
+ const imageURL = new URL(imageObject.url);
31
+ const siteURL = new URL(siteDomain);
32
+
33
+ if (imageURL.origin !== siteURL.origin) {
34
+ // If the image domain doesn't match the site's domain, set external flag
35
+ isExternalImage = true;
23
36
  } else {
24
- let imageUrlMinusBase = imageObject.url.replace( siteDomain+'/app/uploads','' ); // remove base and directory
25
- resizedImageUrl = imageOptionsString + imageUrlMinusBase;
26
- resizedImageUrl = siteDomain + '/' + resizedImageUrl;
37
+ // Image from current site, modify URL if not SVG
38
+ if (imageObject.url.endsWith('.svg')) {
39
+ resizedImageUrl = imageObject.url;
40
+ } else {
41
+ let imageUrlMinusBase = imageObject.url.replace(siteDomain + '/app/uploads', ''); // remove base and directory
42
+ resizedImageUrl = siteDomain + '/' + imageOptionsString + imageUrlMinusBase;
43
+ }
27
44
  }
28
45
  }
29
-
46
+
30
47
  return (
31
48
  <div className={extraClass ? componentClass + ' ' + extraClass : componentClass}>
32
- {imageObject.hasOwnProperty('url') && imageObject.url !== '' ? //Has image
49
+ {imageObject.hasOwnProperty('url') && imageObject.url !== '' ? ( // Has image
33
50
  <MediaUploadCheck>
34
51
  <div className={componentClass + "__media-wrapper"}>
35
- <img
36
- className={componentClass + "__media"}
37
- src={resizedImageUrl}
38
- alt={imageObject.alt}
52
+ {isExternalImage ? (
53
+ // Display text for external images
54
+ <p style={{ textAlign: 'left', fontWeight: 'bold' }}>⚠️This image has been copied from another website or loaded improperly. Please replace it.</p>
55
+ ) : (
56
+ // Display image for internal images
57
+ <img
58
+ className={componentClass + "__media"}
59
+ src={resizedImageUrl}
60
+ alt={imageObject.alt}
39
61
  />
40
- {showCrop && imageObject && typeof imageObject.crop !== 'undefined' &&
62
+ )}
63
+ {!isExternalImage && showCrop && imageObject && typeof imageObject.crop !== 'undefined' && (
41
64
  <>
42
65
  <AlignmentMatrixControl
43
- value={ imageObject.crop }
66
+ value={imageObject.crop}
44
67
  onChange={(value) => updateImageCrop(setAttributes, value, imageObject, imageRef)}
45
68
  />
46
69
  </>
47
- }
70
+ )}
48
71
  </div>
49
72
  <EditImageButtons
50
73
  componentClass={componentClass}
@@ -55,34 +78,32 @@ export const ImagePicker = ({ setAttributes, imageObject = {}, extraClass, image
55
78
  imageId={imageObject.id}
56
79
  />
57
80
  </MediaUploadCheck>
58
- : //No image
81
+ ) : ( // No image
59
82
  <UploadImageButton
60
83
  componentClass={componentClass}
61
84
  setAttributes={setAttributes}
62
- imageRef={imageRef}
85
+ imageRef={imageRef}
63
86
  buttonText={buttonText}
64
87
  />
65
- }
66
-
67
-
68
-
88
+ )}
69
89
  </div>
70
- )
90
+ );
71
91
  };
72
92
 
93
+
73
94
  /*
74
95
  * Image Picker Panel Body
75
96
  * Used for Inspector Controls
76
97
  */
77
98
  export const ImagePickerPanelBody = ({ setAttributes, imageObject, imageRef = null, title = 'Image', showCrop = true }) => {
78
- return(
99
+ return (
79
100
  <PanelBody title={title} initialOpen={true}>
80
101
  <ImagePicker
81
- setAttributes={setAttributes}
82
- imageRef={imageRef}
102
+ setAttributes={setAttributes}
103
+ imageRef={imageRef}
83
104
  imageObject={imageObject}
84
105
  showCrop={showCrop}
85
- />
106
+ />
86
107
  </PanelBody>
87
108
  )
88
109
  }
@@ -94,7 +115,7 @@ export const ImagePickerPanelBody = ({ setAttributes, imageObject, imageRef = nu
94
115
 
95
116
  export const ImagePickerPreview = ({
96
117
  setAttributes,
97
- imageObject = {},
118
+ imageObject = {},
98
119
  blockClass,
99
120
  imageClass,
100
121
  width = 500,
@@ -104,44 +125,49 @@ export const ImagePickerPreview = ({
104
125
  buttonText = 'Select image'
105
126
  }) => {
106
127
 
107
- let componentClass = 'component-image-picker-preview';
108
- let imageElementClass = '';
109
- let imageElementWrapperClass = ''
128
+ let componentClass = 'component-image-picker-preview';
129
+ let imageElementClass = '';
130
+ let imageElementWrapperClass = '';
110
131
 
111
-
112
- if( imageClass ){//Image class
113
- imageElementClass = blockClass + imageClass;
132
+ if (imageClass) { // Image class
133
+ imageElementClass = blockClass + imageClass;
114
134
  imageElementWrapperClass = blockClass + imageClass + '-wrapper';
115
-
116
- } else if( blockClass ){//Block class
117
- imageElementClass = blockClass + '__image';
135
+ } else if (blockClass) { // Block class
136
+ imageElementClass = blockClass + '__image';
118
137
  imageElementWrapperClass = blockClass + '__image-wrapper';
119
138
  }
120
139
 
121
-
122
- let imagecrop = crop ? '1':'0';
123
-
124
- if(imageObject.crop){
140
+ let imagecrop = crop ? '1' : '0';
141
+ if (imageObject.crop) {
125
142
  imagecrop = imageObject.crop.replace(/\s+/g, '-');
126
143
  }
127
144
 
128
- let imageOptionsString = 'images/width='+width+',height='+height+',crop='+imagecrop;
129
- let imageOptionsStringDouble = 'images/width='+width*2+',height='+height*2+',crop='+imagecrop;
145
+ let imageOptionsString = `images/width=${width},height=${height},crop=${imagecrop}`;
146
+ let imageOptionsStringDouble = `images/width=${width * 2},height=${height * 2},crop=${imagecrop}`;
130
147
  let resizedImageUrl = '';
131
148
  let resizedImageUrlDouble = '';
132
149
 
133
- if(imageObject.hasOwnProperty('url') && imageObject.url !== ''){
134
-
135
- let imageUrlMinusBase = imageObject.url.replace( siteDomain+'/app/uploads','' ); // remove base and directory
136
-
137
- if(imageObject.url.endsWith('.svg')) {
150
+ if (imageObject.hasOwnProperty('url') && imageObject.url !== '') {
151
+ const imageURL = new URL(imageObject.url);
152
+ const siteURL = new URL(siteDomain);
153
+
154
+ // Check if the image domain matches the current site's domain
155
+ if (imageURL.origin === siteURL.origin) {
156
+ // Same domain: remove base directory
157
+ let imageUrlMinusBase = imageObject.url.replace(siteDomain + '/app/uploads', '');
158
+
159
+ if (imageObject.url.endsWith('.svg')) {
160
+ resizedImageUrl = imageObject.url;
161
+ resizedImageUrlDouble = imageObject.url;
162
+ } else {
163
+ // Construct resized URLs for images with options
164
+ resizedImageUrl = `${siteDomain}/${imageOptionsString}${imageUrlMinusBase}`;
165
+ resizedImageUrlDouble = `${siteDomain}/${imageOptionsStringDouble}${imageUrlMinusBase}`;
166
+ }
167
+ } else {
168
+ // Different domain: keep the original URL
138
169
  resizedImageUrl = imageObject.url;
139
170
  resizedImageUrlDouble = imageObject.url;
140
- } else {
141
- resizedImageUrl = imageOptionsString + imageUrlMinusBase;
142
- resizedImageUrl = siteDomain + '/' + resizedImageUrl;
143
- resizedImageUrlDouble = imageOptionsStringDouble + imageUrlMinusBase
144
- resizedImageUrlDouble = siteDomain + '/' + resizedImageUrlDouble;
145
171
  }
146
172
  } else {
147
173
  componentClass += ' no-image';
@@ -149,33 +175,33 @@ export const ImagePickerPreview = ({
149
175
 
150
176
  return (
151
177
  <div className={imageElementWrapperClass ? componentClass + ' ' + imageElementWrapperClass : componentClass}>
152
- {imageObject.hasOwnProperty('url') && imageObject.url !== '' ? //Has image
178
+ {imageObject.hasOwnProperty('url') && imageObject.url !== '' ? ( // Has image
153
179
  <MediaUploadCheck>
154
180
  <img
155
- className={imageElementClass ? imageElementClass : ''}
181
+ className={imageElementClass || ''}
156
182
  src={resizedImageUrl}
157
- srcSet={resizedImageUrl+' 1x, '+resizedImageUrlDouble+' 2x'}
158
- alt={imageObject.alt}
183
+ srcSet={`${resizedImageUrl} 1x, ${resizedImageUrlDouble} 2x`}
184
+ alt={imageObject.alt}
159
185
  />
160
186
  <EditImageButtons
161
187
  componentClass={componentClass}
162
188
  setAttributes={setAttributes}
163
- imageRef={imageRef}
189
+ imageRef={imageRef}
164
190
  replaceText=''
165
191
  removeText=''
166
192
  imageId={imageObject.id}
167
193
  />
168
194
  </MediaUploadCheck>
169
- : //No image
195
+ ) : ( // No image
170
196
  <UploadImageButton
171
197
  componentClass={componentClass}
172
198
  setAttributes={setAttributes}
173
- imageRef={imageRef}
199
+ imageRef={imageRef}
174
200
  buttonText={buttonText}
175
201
  />
176
- }
202
+ )}
177
203
  </div>
178
- )
204
+ );
179
205
  };
180
206
 
181
207
  // ============= Image Controls (appear over image within editor)
@@ -201,7 +227,7 @@ export const EditImageButtons = ({ componentClass, setAttributes, replaceText, r
201
227
  <Button
202
228
  className={componentClass + "__edit-button"}
203
229
  isDestructive
204
- onClick={ (media) => {
230
+ onClick={(media) => {
205
231
  updateImageAttr(setAttributes, false, imageRef)
206
232
  }}
207
233
  icon="remove"
@@ -239,12 +265,14 @@ export const UploadImageButton = ({ componentClass, setAttributes, imageRef, but
239
265
  const updateImageCrop = (setAttributes, crop, imageObject, imageRef) => {
240
266
  imageObject.crop = crop;
241
267
 
242
- setAttributes({ [imageRef]: {
243
- id: imageObject.id,
244
- url: imageObject.url,
245
- alt: imageObject.alt,
246
- crop: crop
247
- } }); //used to update imagePickerPreview
268
+ setAttributes({
269
+ [imageRef]: {
270
+ id: imageObject.id,
271
+ url: imageObject.url,
272
+ alt: imageObject.alt,
273
+ crop: crop
274
+ }
275
+ }); //used to update imagePickerPreview
248
276
  }
249
277
 
250
278
  const updateImageAttr = (
@@ -256,7 +284,7 @@ const updateImageAttr = (
256
284
  imageRef ??= 'imageObject';
257
285
 
258
286
  let newImageUrl = media ? media.sizes.full.url : ''
259
-
287
+
260
288
 
261
289
  setAttributes({
262
290
  [imageRef]: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "base-js-sw",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "Reusable Gutenberg block components for WordPress projects",
5
5
  "main": "index.js",
6
6
  "author": "Shape Works",