Skip to content

Commit

Permalink
Merge c9f4285 into a9e38da
Browse files Browse the repository at this point in the history
  • Loading branch information
gmsgowtham committed May 20, 2023
2 parents a9e38da + c9f4285 commit 47ae227
Show file tree
Hide file tree
Showing 12 changed files with 826 additions and 5 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Markdown renderer for React Native powered by
## Installation

```sh
yarn add react-native-marked
yarn add react-native-marked react-native-svg
```

## Usage
Expand Down
1 change: 1 addition & 0 deletions examples/react-native-marked-sample/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"react": "18.0.0",
"react-dom": "18.0.0",
"react-native": "0.69.9",
"react-native-svg": "12.3.0",
"react-native-web": "~0.18.7"
},
"devDependencies": {
Expand Down
3 changes: 3 additions & 0 deletions examples/react-native-marked-sample/src/const.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ Autoconverted link https://github.com/nodeca/pica (enable linkify to see)
## Images
![svg](https://www.svgrepo.com/show/513268/beer.svg)
![Minion](https://octodex.github.com/images/minion.png)
![Stormtroopocat](https://octodex.github.com/images/stormtroopocat.jpg "The Stormtroopocat")
Expand All @@ -130,6 +131,8 @@ Like links, Images also have a footnote style syntax
With a reference later in the document defining the URL location:
[id]: https://octodex.github.com/images/dojocat.jpg "The Dojocat"
[![SVG Repo](https://www.svgrepo.com/show/513268/beer.svg "SVG Repo")](https://www.svgrepo.com)
`;

export { MD_STRING };
86 changes: 85 additions & 1 deletion examples/react-native-marked-sample/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2379,6 +2379,11 @@ body-parser@1.19.0:
raw-body "2.4.0"
type-is "~1.6.17"

boolbase@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==

bplist-creator@0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/bplist-creator/-/bplist-creator-0.1.0.tgz#018a2d1b587f769e379ef5519103730f8963ba1e"
Expand Down Expand Up @@ -2913,6 +2918,30 @@ css-in-js-utils@^2.0.0:
hyphenate-style-name "^1.0.2"
isobject "^3.0.1"

css-select@^4.2.1:
version "4.3.0"
resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.3.0.tgz#db7129b2846662fd8628cfc496abb2b59e41529b"
integrity sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==
dependencies:
boolbase "^1.0.0"
css-what "^6.0.1"
domhandler "^4.3.1"
domutils "^2.8.0"
nth-check "^2.0.1"

css-tree@^1.0.0-alpha.39:
version "1.1.3"
resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.1.3.tgz#eb4870fb6fd7707327ec95c2ff2ab09b5e8db91d"
integrity sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==
dependencies:
mdn-data "2.0.14"
source-map "^0.6.1"

css-what@^6.0.1:
version "6.1.0"
resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4"
integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==

csstype@^3.0.2:
version "3.1.1"
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.1.tgz#841b532c45c758ee546a11d5bd7b7b473c8c30b9"
Expand Down Expand Up @@ -3065,6 +3094,36 @@ dir-glob@^3.0.1:
dependencies:
path-type "^4.0.0"

dom-serializer@^1.0.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.4.1.tgz#de5d41b1aea290215dc45a6dae8adcf1d32e2d30"
integrity sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==
dependencies:
domelementtype "^2.0.1"
domhandler "^4.2.0"
entities "^2.0.0"

domelementtype@^2.0.1, domelementtype@^2.2.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d"
integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==

domhandler@^4.2.0, domhandler@^4.3.1:
version "4.3.1"
resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.1.tgz#8d792033416f59d68bc03a5aa7b018c1ca89279c"
integrity sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==
dependencies:
domelementtype "^2.2.0"

domutils@^2.8.0:
version "2.8.0"
resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135"
integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==
dependencies:
dom-serializer "^1.0.1"
domelementtype "^2.2.0"
domhandler "^4.2.0"

ee-first@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
Expand Down Expand Up @@ -3105,6 +3164,11 @@ enhanced-resolve@^5.10.0:
graceful-fs "^4.2.4"
tapable "^2.2.0"

entities@^2.0.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55"
integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==

env-editor@^0.4.1:
version "0.4.2"
resolved "https://registry.yarnpkg.com/env-editor/-/env-editor-0.4.2.tgz#4e76568d0bd8f5c2b6d314a9412c8fe9aa3ae861"
Expand Down Expand Up @@ -4641,6 +4705,11 @@ md5hex@^1.0.0:
resolved "https://registry.yarnpkg.com/md5hex/-/md5hex-1.0.0.tgz#ed74b477a2ee9369f75efee2f08d5915e52a42e8"
integrity sha512-c2YOUbp33+6thdCUi34xIyOU/a7bvGKj/3DB1iaPMTuPHf/Q2d5s4sn1FaCOO43XkXggnb08y5W2PU8UNYNLKQ==

mdn-data@2.0.14:
version "2.0.14"
resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50"
integrity sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==

media-typer@0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
Expand Down Expand Up @@ -5191,6 +5260,13 @@ npm-run-path@^2.0.0:
dependencies:
path-key "^2.0.0"

nth-check@^2.0.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d"
integrity sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==
dependencies:
boolbase "^1.0.0"

nullthrows@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/nullthrows/-/nullthrows-1.1.1.tgz#7818258843856ae971eae4208ad7d7eb19a431b1"
Expand Down Expand Up @@ -5697,6 +5773,14 @@ react-native-gradle-plugin@^0.0.7:
resolved "https://registry.yarnpkg.com/react-native-gradle-plugin/-/react-native-gradle-plugin-0.0.7.tgz#96602f909745239deab7b589443f14fce5da2056"
integrity sha512-+4JpbIx42zGTONhBTIXSyfyHICHC29VTvhkkoUOJAh/XHPEixpuBduYgf6Y4y9wsN1ARlQhBBoptTvXvAFQf5g==

react-native-svg@12.3.0:
version "12.3.0"
resolved "https://registry.yarnpkg.com/react-native-svg/-/react-native-svg-12.3.0.tgz#40f657c5d1ee366df23f3ec8dae76fd276b86248"
integrity sha512-ESG1g1j7/WLD7X3XRFTQHVv0r6DpbHNNcdusngAODIxG88wpTWUZkhcM3A2HJTb+BbXTFDamHv7FwtRKWQ/ALg==
dependencies:
css-select "^4.2.1"
css-tree "^1.0.0-alpha.39"

react-native-web@~0.18.7:
version "0.18.9"
resolved "https://registry.yarnpkg.com/react-native-web/-/react-native-web-0.18.9.tgz#f5032e0b32ebe99c0ab22d13dbd8ca2944b08f12"
Expand Down Expand Up @@ -6305,7 +6389,7 @@ source-map@^0.5.6:
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==

source-map@^0.6.0, source-map@~0.6.1:
source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
Expand Down
9 changes: 7 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
"@types/react": "18.2.6",
"@types/react-native": "0.72.0",
"@types/react-native-table-component": "1.2.4",
"@types/svg-parser": "^2.0.3",
"commitlint": "17.6.3",
"danger": "11.2.6",
"jest": "29.5.0",
Expand All @@ -80,7 +81,8 @@
},
"peerDependencies": {
"react": "^16.8.6 || ^17.0.0 || ^18.0.0",
"react-native": ">=0.60.0"
"react-native": ">=0.60.0",
"react-native-svg": ">=13.0.0"
},
"jest": {
"preset": "react-native",
Expand Down Expand Up @@ -159,6 +161,9 @@
"@jsamr/counter-style": "2.0.2",
"@jsamr/react-native-li": "2.3.1",
"marked": "4.3.0",
"react-native-table-component": "1.2.2"
"react-native-svg": "13.9.0",
"react-native-table-component": "1.2.2",
"svg-parser": "^2.0.4",
"svgps": "0.8.0"
}
}
108 changes: 108 additions & 0 deletions src/components/MDSvg.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import React, {
memo,
type FunctionComponent,
useEffect,
useState,
useRef,
} from "react";
import { ActivityIndicator, View, type LayoutChangeEvent } from "react-native";
import { SvgFromXml } from "react-native-svg";
import { getSvgDimensions } from "./../utils/svg";

type MDSvgProps = {
uri: string;
alt?: string;
};

type MdSvgState = {
viewBox: string;
width: number;
height: number;
svg: string;
isLoading: boolean;
error: boolean;
aspectRatio?: number;
};

const MDSvg: FunctionComponent<MDSvgProps> = ({ uri, alt = "image" }) => {
const isFirstLoad = useRef<boolean>(false);
const [layoutWidth, setLayoutWidth] = useState<number>(0);
const [svgState, setSvgState] = useState<MdSvgState>({
viewBox: "",
width: 0,
height: 0,
svg: "",
isLoading: true,
error: false,
aspectRatio: undefined,
});
useEffect(() => {
const fetchSvg = async () => {
try {
const res = await fetch(uri);
const text = await res.text();
if (res.status !== 200) {
throw new Error("Status is not 200");
}
const { viewBox, width, height } = getSvgDimensions(text);

setSvgState({
width,
height,
viewBox,
svg: text,
isLoading: false,
error: false,
aspectRatio: width / height,
});
} catch (e) {
setSvgState((state) => ({
...state,
error: true,
isLoading: false,
}));
}
};

fetchSvg();
}, []);

const onLayout = (event: LayoutChangeEvent) => {
if (!isFirstLoad.current) {
setLayoutWidth(event.nativeEvent.layout.width ?? 0);
isFirstLoad.current = true;
}
};

const getWidth = () => {
if (layoutWidth && svgState.width) {
return Math.min(layoutWidth, svgState.width);
}
return "100%";
};

return (
<View
style={{ width: getWidth(), aspectRatio: svgState.aspectRatio }}
onLayout={onLayout}
>
{svgState.isLoading ? (
<ActivityIndicator size={"small"} />
) : (
<SvgFromXml
xml={svgState.svg}
width={"100%"}
height={"100%"}
viewBox={svgState.viewBox}
aria-label={alt}
accessibilityRole="image"
accessibilityLabel={alt}
accessibilityHint={undefined}
testID="react-native-marked-md-svg"
/>
)}
</View>
);
};

export default memo(MDSvg);
7 changes: 6 additions & 1 deletion src/lib/Renderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import MDImage from "./../components/MDImage";
import { onLinkPress } from "../utils/handlers";
import type { RendererInterface } from "./types";
import { getTableWidthArr } from "../utils/table";
import MDSvg from "./../components/MDSvg";

class Renderer implements RendererInterface {
private slugPrefix = "react-native-marked-ele";
Expand Down Expand Up @@ -112,7 +113,11 @@ class Renderer implements RendererInterface {
}

image(uri: string, alt?: string, style?: ImageStyle): ReactNode {
return <MDImage key={this.getKey()} uri={uri} alt={alt} style={style} />;
const key = this.getKey();
if (uri.endsWith(".svg")) {
return <MDSvg uri={uri} key={key} />;
}
return <MDImage key={key} uri={uri} alt={alt} style={style} />;
}

strong(children: ReactNode[], styles?: TextStyle): ReactNode {
Expand Down
30 changes: 30 additions & 0 deletions src/lib/__tests__/Markdown.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,36 @@ describe("Images", () => {
expect(tree).toMatchSnapshot();
});
});
it("SVG images", async () => {
const r = render(
<Markdown
value={"![svg](https://www.svgrepo.com/show/513268/beer.svg)"}
/>,
);
await waitFor(() => {
expect(
screen.queryAllByTestId("react-native-marked-md-svg"),
).toBeDefined();
const tree = r.toJSON();
expect(tree).toMatchSnapshot();
});
});
it("SVG Linking", async () => {
const r = render(
<Markdown
value={
'[![SVG Repo](https://www.svgrepo.com/show/513268/beer.svg "SVG Repo")](https://www.svgrepo.com)'
}
/>,
);
await waitFor(() => {
expect(
screen.queryAllByTestId("react-native-marked-md-svg"),
).toBeDefined();
const tree = r.toJSON();
expect(tree).toMatchSnapshot();
});
});
});

// https://www.markdownguide.org/basic-syntax/#escaping-characters
Expand Down
Loading

0 comments on commit 47ae227

Please sign in to comment.