@ndlib/component-library 0.0.101 → 0.0.102

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,6 +3,7 @@ import { render } from '../../../utils/test';
3
3
  import { Icon } from '.';
4
4
  import { SPACING } from '../../../theme';
5
5
  import { FONT_SIZE, fontSizeMap } from '../../../theme/typography';
6
+ import { vitest } from 'vitest';
6
7
  const MockIcon = () => {
7
8
  return _jsx("div", { children: "Mock Icon" });
8
9
  };
@@ -23,4 +24,11 @@ describe('Icon', () => {
23
24
  padding: SPACING[1],
24
25
  });
25
26
  });
27
+ it('icon can be clicked', () => {
28
+ const onClick = vitest.fn();
29
+ const { getByLabelText } = render(_jsx(Icon, { icon: MockIcon, sx: { p: 1 }, onClick: onClick, "aria-label": "My Icon" }));
30
+ const icon = getByLabelText('My Icon');
31
+ icon.click();
32
+ expect(onClick).toHaveBeenCalled();
33
+ });
26
34
  });
@@ -20,7 +20,7 @@ export const Icon = (_a) => {
20
20
  if (onClick && !rest['aria-label']) {
21
21
  flagInDevelopment('Icon component with onClick should have an aria-label and tabIndex={0}');
22
22
  }
23
- return (_jsx("div", Object.assign({ tabIndex: onClick ? 0 : undefined, role: onClick ? 'button' : 'none', sx: Object.assign(Object.assign({}, sx), { fontSize: size, display: 'flex', alignItems: 'center', justifyContent: 'center', ':hover': onClick
23
+ return (_jsx("div", Object.assign({ tabIndex: onClick ? 0 : undefined, role: onClick ? 'button' : 'none', onClick: onClick, sx: Object.assign(Object.assign({}, sx), { fontSize: size, display: 'flex', alignItems: 'center', justifyContent: 'center', ':hover': onClick
24
24
  ? {
25
25
  cursor: 'pointer',
26
26
  transform: 'scale(1.05)',
@@ -7,5 +7,4 @@ export declare const Default: Story;
7
7
  export declare const WithHtml: Story;
8
8
  export declare const CustomizeImages: Story;
9
9
  export declare const CustomizeStyles: Story;
10
- export declare const CustomHtmlSanitize: Story;
11
10
  export declare const NoHtml: Story;
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { DEFAULT_ALLOWED_ATTRIBUTES, DEFAULT_ALLOWED_TAGS, Markdown } from '.';
2
+ import { Markdown } from '.';
3
3
  import { FONT_WEIGHT } from '../../../theme/typography';
4
4
  import { COLOR } from '../../../theme/colors';
5
5
  const meta = {
@@ -59,6 +59,14 @@ reprehenderit in voluptate velit esse cillum dolore eu fugiat
59
59
  nulla pariatur.
60
60
 
61
61
  https://this-should-be-auto-linked.nd.edu
62
+
63
+ While Gura says that the exhibit was inspired by the themes of the Medieval conference and will appeal to its attendees, the displays are curated to interest Notre Dame students and faculty across various disciplines, as well as the general public.
64
+
65
+ “I'm trying to pick items to tell a story that viewers can appreciate on different levels at the same time,” he said.
66
+
67
+ To tell that story, Gura decided to give each of the seven cases housing this exhibit a theme.
68
+
69
+ > “I think it's an exciting way to create a journey through time and space using the objects themselves as the primary storyteller,” he said. “They will drive the narrative from case to case. You can be exposed to different things that the average person never really thought about.”
62
70
  `;
63
71
  export const Default = {
64
72
  render: (args) => _jsx(Markdown, Object.assign({}, args)),
@@ -67,14 +75,15 @@ export const Default = {
67
75
  },
68
76
  };
69
77
  const htmlContent = `
70
- ## HTML Content
71
- <p style='color: red;'>hello world </p>
72
- <img
73
- style="width: 300px"
74
- src="https://s3.amazonaws.com/resources.library.nd.edu/images/website/search.banner.fall.jpg"
75
- ></img>
76
- <a href="https://google.com" class="embedly-card" data-card-width="100px" data-card-controls="0">Embedded content: https://google.com</a>
77
- <iframe src="https://www.facebook.com/plugins/video.php?href=https%3A%2F%2Fwww.facebook.com%2FNDLibraries%2Fvideos%2F1673794309311939%2F&show_text=0&width=560" width="560" height="315" style="border:none;overflow:hidden" scrolling="no" frameborder="0" ></iframe>
78
+ ## HTML Content
79
+ <p style='color: red;'>hello world </p>
80
+ > test
81
+ <img
82
+ style="width: 300px"
83
+ src="https://s3.amazonaws.com/resources.library.nd.edu/images/website/search.banner.fall.jpg"
84
+ ></img>
85
+ <a href="https://google.com" class="embedly-card" data-card-width="100px" data-card-controls="0">Embedded content: https://google.com</a>
86
+ <iframe src="https://www.facebook.com/plugins/video.php?href=https%3A%2F%2Fwww.facebook.com%2FNDLibraries%2Fvideos%2F1673794309311939%2F&show_text=0&width=560" width="560" height="315" style="border:none;overflow:hidden" scrolling="no" frameborder="0" ></iframe>
78
87
  `;
79
88
  export const WithHtml = {
80
89
  render: (args) => _jsx(Markdown, Object.assign({}, args)),
@@ -102,17 +111,6 @@ export const CustomizeStyles = {
102
111
  content: startingContent,
103
112
  },
104
113
  };
105
- export const CustomHtmlSanitize = {
106
- render: (args) => _jsx(Markdown, Object.assign({}, args)),
107
- args: {
108
- enableHtml: true,
109
- sanitizeHtmlOptions: {
110
- allowedAttributes: Object.assign(Object.assign({}, DEFAULT_ALLOWED_ATTRIBUTES), { p: ['style'], img: ['src', 'style'] }),
111
- allowedTags: [...DEFAULT_ALLOWED_TAGS, 'img'],
112
- },
113
- content: htmlContent,
114
- },
115
- };
116
114
  export const NoHtml = {
117
115
  render: (args) => _jsx(Markdown, Object.assign({}, args)),
118
116
  args: {
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { render } from '../../../utils/test';
3
- import { DEFAULT_ALLOWED_TAGS, Markdown } from '.';
3
+ import { Markdown } from '.';
4
4
  const testMarkdown = `
5
5
  # Inline styles
6
6
  This paragraph has __bold content__ and **more bold content** and _italic content_ and *more italic content*
@@ -37,6 +37,14 @@ reprehenderit in voluptate velit esse cillum dolore eu fugiat
37
37
  nulla pariatur.
38
38
 
39
39
  https://this-should-be-auto-linked.nd.edu
40
+
41
+ While Gura says that the exhibit was inspired by the themes of the Medieval conference and will appeal to its attendees, the displays are curated to interest Notre Dame students and faculty across various disciplines, as well as the general public.
42
+
43
+ “I'm trying to pick items to tell a story that viewers can appreciate on different levels at the same time,” he said.
44
+
45
+ To tell that story, Gura decided to give each of the seven cases housing this exhibit a theme.
46
+
47
+ > “I think it's an exciting way to create a journey through time and space using the objects themselves as the primary storyteller,” he said. “They will drive the narrative from case to case. You can be exposed to different things that the average person never really thought about.”
40
48
  `;
41
49
  const htmlMarkdown = `
42
50
  ## HTML Content
@@ -87,7 +95,7 @@ describe('Markdown', () => {
87
95
  expect(getAllByRole('link')).toBeDefined();
88
96
  expect(() => getByText('&nbsp;')).toThrow();
89
97
  expect(container.getElementsByTagName('script')).toHaveLength(0);
90
- expect(container.getElementsByTagName('img')).toHaveLength(0);
98
+ expect(container.getElementsByTagName('img')).toHaveLength(1);
91
99
  expect(container.getElementsByTagName('iframe')).toHaveLength(1);
92
100
  });
93
101
  it('does not render html when disabled', () => {
@@ -96,10 +104,4 @@ describe('Markdown', () => {
96
104
  expect(container.getElementsByTagName('script')).toHaveLength(0);
97
105
  expect(container.getElementsByTagName('iframe')).toHaveLength(0);
98
106
  });
99
- it('supports customizing html sanitization', () => {
100
- const { container } = render(_jsx(Markdown, { content: htmlMarkdown, enableHtml: true, sanitizeHtmlOptions: {
101
- allowedTags: DEFAULT_ALLOWED_TAGS.concat(['img']),
102
- } }));
103
- expect(container.getElementsByTagName('img')).toHaveLength(1);
104
- });
105
107
  });
@@ -11,10 +11,6 @@ type MarkdownProps = StyledElementProps<HTMLDivElement, {
11
11
  enableHtml?: boolean;
12
12
  imageStyles?: React.CSSProperties;
13
13
  headingLevelOffset?: number;
14
- sanitizeHtmlOptions?: {
15
- allowedTags?: string[];
16
- allowedAttributes?: sanitizeHtml.IOptions['allowedAttributes'];
17
- };
18
14
  customStyles?: Record<string, StylesProp>;
19
15
  }>;
20
16
  export declare const Markdown: React.FC<MarkdownProps>;
@@ -22,24 +22,52 @@ import remarkGfm from 'remark-gfm';
22
22
  import { BlockQuote } from '../BlockQuote';
23
23
  export const DEFAULT_ALLOWED_TAGS = sanitizeHtml.defaults.allowedTags.concat([
24
24
  'iframe',
25
+ 'img',
25
26
  ]);
26
27
  export const DEFAULT_ALLOWED_ATTRIBUTES = Object.assign(Object.assign({}, sanitizeHtml.defaults.allowedAttributes), { iframe: ['*'], a: sanitizeHtml.defaults.allowedAttributes.a.concat([
27
28
  'class',
28
29
  'data-card-width',
29
30
  'data-card-controls',
30
31
  ]) });
32
+ const parseBlockquotes = (content) => {
33
+ const contentArray = content.split('\n');
34
+ let newContent = '';
35
+ let isAddingBlockquote = false;
36
+ for (const line of contentArray) {
37
+ if (line.startsWith('> ') && !isAddingBlockquote) {
38
+ const newLine = line.replace('> ', '');
39
+ newContent += `<blockquote>${newLine}`;
40
+ isAddingBlockquote = true;
41
+ }
42
+ else if (line.startsWith('> ') && isAddingBlockquote) {
43
+ newContent += line.replace('> ', '');
44
+ }
45
+ else if (isAddingBlockquote) {
46
+ newContent += `</blockquote>\n\n${line}`;
47
+ isAddingBlockquote = false;
48
+ }
49
+ else {
50
+ newContent += line;
51
+ }
52
+ }
53
+ if (isAddingBlockquote) {
54
+ newContent += '</blockquote>';
55
+ }
56
+ return newContent;
57
+ };
31
58
  const dynamicTopMarginStyles = {
32
59
  [firstChildAltSelector]: {
33
60
  mt: 0,
34
61
  },
35
62
  };
36
63
  export const Markdown = (_a) => {
37
- var { content, enableHtml, sanitizeHtmlOptions, imageStyles, customStyles = {}, headingLevelOffset = 1 } = _a, rest = __rest(_a, ["content", "enableHtml", "sanitizeHtmlOptions", "imageStyles", "customStyles", "headingLevelOffset"]);
64
+ var { content, enableHtml, imageStyles, customStyles = {}, headingLevelOffset = 1 } = _a, rest = __rest(_a, ["content", "enableHtml", "imageStyles", "customStyles", "headingLevelOffset"]);
38
65
  let sanitizedContent = content;
39
66
  if (enableHtml) {
40
- sanitizedContent = sanitizeHtml(content, {
41
- allowedTags: (sanitizeHtmlOptions === null || sanitizeHtmlOptions === void 0 ? void 0 : sanitizeHtmlOptions.allowedTags) || DEFAULT_ALLOWED_TAGS,
42
- allowedAttributes: (sanitizeHtmlOptions === null || sanitizeHtmlOptions === void 0 ? void 0 : sanitizeHtmlOptions.allowedAttributes) || DEFAULT_ALLOWED_ATTRIBUTES,
67
+ sanitizedContent = parseBlockquotes(content);
68
+ sanitizedContent = sanitizeHtml(sanitizedContent, {
69
+ allowedTags: DEFAULT_ALLOWED_TAGS,
70
+ allowedAttributes: DEFAULT_ALLOWED_ATTRIBUTES,
43
71
  });
44
72
  }
45
73
  return (_jsx("div", Object.assign({}, rest, { children: _jsx(ReactMarkdown, Object.assign({ rehypePlugins: enableHtml ? [rehypeRaw, remarkGfm] : [remarkGfm], components: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ndlib/component-library",
3
- "version": "0.0.101",
3
+ "version": "0.0.102",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "files": [