@eeacms/volto-slate-footnote 7.0.1 → 7.1.1

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/CHANGELOG.md CHANGED
@@ -4,6 +4,17 @@ All notable changes to this project will be documented in this file. Dates are d
4
4
 
5
5
  Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
6
6
 
7
+ ### [7.1.1](https://github.com/eea/volto-slate-footnote/compare/7.1.0...7.1.1) - 16 September 2024
8
+
9
+ ### [7.1.0](https://github.com/eea/volto-slate-footnote/compare/7.0.1...7.1.0) - 13 September 2024
10
+
11
+ #### :rocket: New Features
12
+
13
+ - feat: autodetect links and use universal link - refs #274052 [dobri1408 - [`9c13101`](https://github.com/eea/volto-slate-footnote/commit/9c13101b62b1df150e1b3dbb93807df60a074ad5)]
14
+
15
+ #### :hammer_and_wrench: Others
16
+
17
+ - Release 7.1.0 [alin - [`c15afb0`](https://github.com/eea/volto-slate-footnote/commit/c15afb0be79ba9c4e3a46e3c190a41db468e88cd)]
7
18
  ### [7.0.1](https://github.com/eea/volto-slate-footnote/compare/7.0.0...7.0.1) - 23 August 2024
8
19
 
9
20
  #### :hammer_and_wrench: Others
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eeacms/volto-slate-footnote",
3
- "version": "7.0.1",
3
+ "version": "7.1.1",
4
4
  "description": "volto-slate-footnote: Volto add-on",
5
5
  "main": "src/index.js",
6
6
  "author": "European Environment Agency: IDM2 A-Team",
@@ -3,13 +3,13 @@ import {
3
3
  openAccordionOrTabIfContainsFootnoteReference,
4
4
  getAllBlocksAndSlateFields,
5
5
  makeFootnoteListOfUniqueItems,
6
- makeFootnote,
7
6
  } from '@eeacms/volto-slate-footnote/editor/utils';
8
7
  import './less/public.less';
9
8
 
10
9
  import { UniversalLink } from '@plone/volto/components';
11
10
 
12
11
  const alphabet = 'abcdefghijklmnopqrstuvwxyz';
12
+ const urlRegex = /https?:\/\/[^\s]+/g;
13
13
 
14
14
  /**
15
15
  * @summary The React component that displays the list of footnotes inserted
@@ -19,6 +19,7 @@ const alphabet = 'abcdefghijklmnopqrstuvwxyz';
19
19
  * @param {Object} props Contains the properties `data` and `properties` as
20
20
  * received from the Volto form.
21
21
  */
22
+
22
23
  const FootnotesBlockView = (props) => {
23
24
  const { data, properties, tabData, content } = props;
24
25
  const { title, global, placeholder = 'Footnotes' } = data;
@@ -75,6 +76,35 @@ const FootnotesBlockView = (props) => {
75
76
  startList = citationIndice;
76
77
  }
77
78
 
79
+ const renderTextWithLinks = (text) => {
80
+ if (!text) return null;
81
+ const parts = text.split(urlRegex);
82
+ const links = text.match(urlRegex);
83
+ let result = [];
84
+
85
+ parts.forEach((part, index) => {
86
+ result.push(
87
+ <div
88
+ dangerouslySetInnerHTML={{
89
+ __html: part,
90
+ }}
91
+ />,
92
+ );
93
+
94
+ if (links && links[index]) {
95
+ result.push(
96
+ <UniversalLink
97
+ key={`link-${index}`}
98
+ href={links[index]}
99
+ openLinkInNewTab={false}
100
+ >
101
+ {links[index]}
102
+ </UniversalLink>,
103
+ );
104
+ }
105
+ });
106
+ return result;
107
+ };
78
108
  return (
79
109
  <div className="footnotes-listing-block">
80
110
  <h3 title={placeholder}>{title}</h3>
@@ -85,16 +115,19 @@ const FootnotesBlockView = (props) => {
85
115
  const { uid, footnote, zoteroId, parentUid } = note;
86
116
  const { refs } = note;
87
117
  const refsList = refs ? Object.keys(refs) : null;
118
+
119
+ // const history = createBrowserHistory();
120
+ // const api = new Api();
121
+ // const store = configureStore(window.__data, history, api);
122
+ const footnoteText = !footnote
123
+ ? ''
124
+ : footnote.replace('<?xml version="1.0"?>', '');
88
125
  return (
89
126
  <li
90
127
  key={`footnote-${zoteroId || uid}`}
91
128
  id={`footnote-${zoteroId || uid}`}
92
129
  >
93
- <div
94
- dangerouslySetInnerHTML={{
95
- __html: makeFootnote(footnote),
96
- }}
97
- />
130
+ <div>{renderTextWithLinks(footnoteText)}</div>
98
131
  {refsList ? (
99
132
  <>
100
133
  {/** some footnotes are never parent so we need the parent to reference */}
@@ -15,9 +15,8 @@ import { UniversalLink } from '@plone/volto/components';
15
15
  * @param {string} footnote
16
16
  * @returns {string} formatted footnote
17
17
  */
18
- const makeFootnote = (footnote) => {
19
- return footnote ? footnote.replace('<?xml version="1.0"?>', '') : '';
20
- };
18
+
19
+ const urlRegex = /https?:\/\/[^\s]+/g;
21
20
 
22
21
  export const FootnoteElement = (props) => {
23
22
  const { attributes, children, element, mode, extras } = props;
@@ -37,7 +36,7 @@ export const FootnoteElement = (props) => {
37
36
  const notesObjResult = isEmpty(metadata)
38
37
  ? makeFootnoteListOfUniqueItems(storeBlocks)
39
38
  : makeFootnoteListOfUniqueItems(blocks);
40
- // will cosider zotero citations and footnote
39
+ // will consider zotero citations and footnote
41
40
  // notesObjResult contains all zotero/footnote as unique, and contain refs for other zotero/footnote
42
41
  const indiceIfZoteroId = data.extra
43
42
  ? [
@@ -52,6 +51,35 @@ export const FootnoteElement = (props) => {
52
51
  : // no extra citations (no multiples)
53
52
  `[${Object.keys(notesObjResult).indexOf(zoteroId) + 1}]`;
54
53
 
54
+ const renderTextWithLinks = (text) => {
55
+ if (!text) return null;
56
+ const parts = text.split(urlRegex);
57
+ const links = text.match(urlRegex);
58
+ let result = [];
59
+
60
+ parts.forEach((part, index) => {
61
+ result.push(
62
+ <div
63
+ dangerouslySetInnerHTML={{
64
+ __html: part,
65
+ }}
66
+ />,
67
+ );
68
+
69
+ if (links && links[index]) {
70
+ result.push(
71
+ <UniversalLink
72
+ key={`link-${index}`}
73
+ href={links[index]}
74
+ openLinkInNewTab={false}
75
+ >
76
+ {links[index]}
77
+ </UniversalLink>,
78
+ );
79
+ }
80
+ });
81
+ return result;
82
+ };
55
83
  const citationIndice = zoteroId // ZOTERO
56
84
  ? indiceIfZoteroId
57
85
  : // FOOTNOTES
@@ -76,13 +104,17 @@ export const FootnoteElement = (props) => {
76
104
  Object.keys(notesObjResult).find(
77
105
  (noteKey) => notesObjResult[noteKey].uid === uid,
78
106
  ) ||
79
- // if not found in parent, search in refs, it might be a footnote references multiple times
107
+ // if not found in parent, search in refs, it might be a footnote referenced multiple times
80
108
  Object.keys(notesObjResult).find(
81
109
  (noteKey) =>
82
110
  notesObjResult[noteKey].uid === uid ||
83
111
  (notesObjResult[noteKey].refs && notesObjResult[noteKey].refs[uid]),
84
112
  );
85
113
 
114
+ const footnoteText = !data.footnote
115
+ ? ''
116
+ : data.footnote.replace('<?xml version="1.0"?>', '');
117
+
86
118
  return (
87
119
  <>
88
120
  {mode === 'view' ? (
@@ -109,7 +141,6 @@ export const FootnoteElement = (props) => {
109
141
  <Popup.Content>
110
142
  <List divided relaxed selection>
111
143
  <List.Item
112
- as={UniversalLink}
113
144
  href={`#footnote-${citationRefId}`}
114
145
  onClick={() =>
115
146
  openAccordionOrTabIfContainsFootnoteReference(
@@ -120,37 +151,34 @@ export const FootnoteElement = (props) => {
120
151
  >
121
152
  <List.Content>
122
153
  <List.Description>
123
- <div
124
- dangerouslySetInnerHTML={{
125
- __html: makeFootnote(data.footnote),
126
- }}
127
- />{' '}
154
+ {renderTextWithLinks(footnoteText)}
128
155
  </List.Description>
129
156
  </List.Content>
130
157
  </List.Item>
131
158
  {data.extra &&
132
- data.extra.map((item) => (
133
- <List.Item
134
- as={UniversalLink}
135
- href={`#footnote-${item.zoteroId || item.uid}`}
136
- onClick={() =>
137
- openAccordionOrTabIfContainsFootnoteReference(
138
- `#footnote-${item.zoteroId || item.uid}`,
139
- )
140
- }
141
- key={`#footnote-${item.zoteroId || item.uid}`}
142
- >
143
- <List.Content>
144
- <List.Description>
145
- <div
146
- dangerouslySetInnerHTML={{
147
- __html: makeFootnote(item.footnote),
148
- }}
149
- />{' '}
150
- </List.Description>
151
- </List.Content>
152
- </List.Item>
153
- ))}
159
+ data.extra.map((item) => {
160
+ const footnoteText = !item.footnote
161
+ ? ''
162
+ : item.footnote.replace('<?xml version="1.0"?>', '');
163
+
164
+ return (
165
+ <List.Item
166
+ href={`#footnote-${item.zoteroId || item.uid}`}
167
+ onClick={() =>
168
+ openAccordionOrTabIfContainsFootnoteReference(
169
+ `#footnote-${item.zoteroId || item.uid}`,
170
+ )
171
+ }
172
+ key={`#footnote-${item.zoteroId || item.uid}`}
173
+ >
174
+ <List.Content>
175
+ <List.Description>
176
+ {renderTextWithLinks(footnoteText)}
177
+ </List.Description>
178
+ </List.Content>
179
+ </List.Item>
180
+ );
181
+ })}
154
182
  </List>
155
183
  </Popup.Content>
156
184
  </Popup>
@@ -173,7 +201,6 @@ export const FootnoteElement = (props) => {
173
201
  <Popup.Content>
174
202
  <List divided relaxed selection>
175
203
  <List.Item
176
- as={UniversalLink}
177
204
  href={`#footnote-${citationRefId}`}
178
205
  onClick={() =>
179
206
  openAccordionOrTabIfContainsFootnoteReference(
@@ -184,18 +211,13 @@ export const FootnoteElement = (props) => {
184
211
  >
185
212
  <List.Content>
186
213
  <List.Description>
187
- <div
188
- dangerouslySetInnerHTML={{
189
- __html: makeFootnote(data.footnote),
190
- }}
191
- />{' '}
214
+ {renderTextWithLinks(footnoteText)}
192
215
  </List.Description>
193
216
  </List.Content>
194
217
  </List.Item>
195
218
  {data.extra &&
196
219
  data.extra.map((item) => (
197
220
  <List.Item
198
- as={UniversalLink}
199
221
  href={`#footnote-${item.zoteroId || item.uid}`}
200
222
  onClick={() =>
201
223
  openAccordionOrTabIfContainsFootnoteReference(
@@ -206,11 +228,7 @@ export const FootnoteElement = (props) => {
206
228
  >
207
229
  <List.Content>
208
230
  <List.Description>
209
- <div
210
- dangerouslySetInnerHTML={{
211
- __html: makeFootnote(item.footnote),
212
- }}
213
- />{' '}
231
+ {renderTextWithLinks(item.footnote)}
214
232
  </List.Description>
215
233
  </List.Content>
216
234
  </List.Item>
@@ -1,15 +1,6 @@
1
1
  import config from '@plone/volto/registry';
2
2
  import { Node } from 'slate';
3
3
  import { getAllBlocks } from '@plone/volto-slate/utils';
4
-
5
- /**
6
- * remove <?xml version="1.0"?> from the string
7
- * @param {*} footnote - xml format
8
- * @returns string
9
- */
10
- export const makeFootnote = (footnote) => {
11
- return footnote ? footnote.replace('<?xml version="1.0"?>', '') : '';
12
- };
13
4
  /**
14
5
  * retrive all slate children of nested objects
15
6
  * @param {object} path - the keys that we want to extract the slate children from
@@ -1,5 +1,4 @@
1
1
  import {
2
- makeFootnote,
3
2
  openAccordionOrTabIfContainsFootnoteReference,
4
3
  getAllBlocksAndSlateFields,
5
4
  } from './utils';
@@ -9,19 +8,6 @@ jest.mock('@plone/volto-slate/utils', () => ({
9
8
  getAllBlocks: jest.fn(),
10
9
  }));
11
10
 
12
- describe('makeFootnote', () => {
13
- it('should remove xml version string from footnote', () => {
14
- const xmlString = '<?xml version="1.0"?>Test text';
15
- const expectedResult = 'Test text';
16
- expect(makeFootnote(xmlString)).toEqual(expectedResult);
17
- });
18
-
19
- it('should return empty string when footnote is null or undefined', () => {
20
- expect(makeFootnote(null)).toEqual('');
21
- expect(makeFootnote(undefined)).toEqual('');
22
- });
23
- });
24
-
25
11
  describe('openAccordionOrTabIfContainsFootnoteReference', () => {
26
12
  it('should open accordion if it contains footnote reference', () => {
27
13
  document.body.innerHTML = `