mirror of
https://gitee.com/baidu/amis.git
synced 2024-11-29 18:48:45 +08:00
Merge pull request #6756 from nwind/feat-ooxml-diagram
feat(office-viewer): 支持图片里的变量
This commit is contained in:
commit
0f8842ffff
@ -71,7 +71,7 @@ Word 渲染支持以下功能:
|
||||
|
||||
> 2.10.0 及以上版本
|
||||
|
||||
默认情况下 word 文档渲染使用流式布局,这样能更好融入到已有页面中,但展现上会和原先的文档有较大差异,且不支持页眉页脚,如果希望能看起来更像桌面端的效果,可以通过 `page` 配置开启分页渲染,只有在分页渲染
|
||||
默认情况下 word 文档渲染使用流式布局,这样能更好融入到已有页面中,但展现上会和原先的文档有较大差异,且不支持页眉页脚,如果希望能看起来更像桌面端的效果,可以通过 `page` 配置开启分页渲染
|
||||
|
||||
```schema: scope="body"
|
||||
{
|
||||
@ -205,7 +205,7 @@ Word 渲染支持以下功能:
|
||||
},
|
||||
{
|
||||
"type": "service",
|
||||
"api": "/api/mock2/sample/mirror?json=%7B%22users%22%3A%5B%7B%22name%22%3A%22u1%22%2C%22age%22%3A10%7D%2C%7B%22name%22%3A%22u2%22%2C%22age%22%3A11%7D%5D%7D",
|
||||
"api": "/api/mock2/sample/mirror?json=%7B%22users%22%3A%5B%7B%22name%22%3A%22u1%22%2C%22age%22%3A10%2C%22img%22%3A%22https%3A%2F%2Fsuda.cdn.bcebos.com%2Fimages%2Famis%2Fai-fake-face.jpg%22%7D%2C%7B%22name%22%3A%22u2%22%2C%22age%22%3A11%7D%5D%7D",
|
||||
"body": [{
|
||||
"type": "office-viewer",
|
||||
"src": "/examples/static/table-list.docx",
|
||||
@ -240,6 +240,41 @@ Word 渲染支持以下功能:
|
||||
|
||||
注意上面的例子用到了 `trackExpression`,默认情况下如果设置了 `enableVar`,每次上层数据变化都会重新渲染文档,如果文档较大可能会有性能问题,这时可以通过配置 `trackExpression` 来限制只有某个数据变化时才重新渲染。
|
||||
|
||||
### 图片中的变量
|
||||
|
||||
> 2.10 及以上版本
|
||||
|
||||
如果要将文档中的图片设置为变量,需要右键对应的图片,选择「查看可选文字」,然后填入类似 `{{img}}` 变量标识,在渲染时图片将替换为这个 `img` 变量的 url 地址
|
||||
|
||||
![word](../../../examples/static/word-alt.png)
|
||||
|
||||
下面是示例
|
||||
|
||||
```schema: scope="body"
|
||||
{
|
||||
"type": "form",
|
||||
"title": "",
|
||||
"wrapWithPanel": false,
|
||||
"body": [
|
||||
{
|
||||
"type": "input-text",
|
||||
"name": "img",
|
||||
"value": "https://suda.cdn.bcebos.com/images/amis/ai-fake-face.jpg",
|
||||
"label": "图片地址"
|
||||
},
|
||||
{
|
||||
"type": "office-viewer",
|
||||
"id": "office-viewer",
|
||||
"src": "/examples/static/image-alt-var.docx",
|
||||
"wordOptions": {
|
||||
"enableVar": true,
|
||||
"padding": "8px"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## 不渲染模式
|
||||
|
||||
通过配置 `display: false` 可以让文档不渲染,虽然不渲染,但还是可以使用后面的下载及打印功能
|
||||
|
BIN
examples/static/image-alt-var.docx
Normal file
BIN
examples/static/image-alt-var.docx
Normal file
Binary file not shown.
Binary file not shown.
BIN
examples/static/word-alt.png
Normal file
BIN
examples/static/word-alt.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 215 KiB |
@ -59,7 +59,7 @@
|
||||
"mobx-state-tree": "^3.17.3",
|
||||
"moment": "^2.19.4",
|
||||
"mpegts.js": "^1.6.10",
|
||||
"ooxml-viewer": "^0.1.2",
|
||||
"ooxml-viewer": "^0.1.3",
|
||||
"prop-types": "^15.6.1",
|
||||
"qrcode.react": "^3.1.0",
|
||||
"rc-overflow": "^1.2.4",
|
||||
|
BIN
packages/ooxml-viewer/__tests__/docx/simple/smart-art.docx
Normal file
BIN
packages/ooxml-viewer/__tests__/docx/simple/smart-art.docx
Normal file
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
import {presetShape} from '../src/openxml/word/drawing/presetShape';
|
||||
import {shapeToSVG} from '../src/openxml/word/drawing/svg/shapeToSVG';
|
||||
import {presetShape} from '../src/openxml/drawing/presetShape';
|
||||
import {shapeToSVG} from '../src/openxml/drawing/svg/shapeToSVG';
|
||||
|
||||
const container = document.getElementById('shapes')! as HTMLElement;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ooxml-viewer",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.3",
|
||||
"description": "office 文档在线预览",
|
||||
"main": "lib/index.js",
|
||||
"module": "esm/index.js",
|
||||
|
@ -508,6 +508,14 @@ export default class Word {
|
||||
return text;
|
||||
}
|
||||
|
||||
loadWordRelXML(relation: Relationship): Document {
|
||||
let path = relation.target;
|
||||
if (relation.part === 'word') {
|
||||
path = 'word/' + path;
|
||||
}
|
||||
return this.getXML(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载图片
|
||||
*/
|
||||
|
@ -1,5 +1,5 @@
|
||||
import {Relationship} from '../../../parse/parseRelationship';
|
||||
import Word from '../../../Word';
|
||||
import {Relationship} from '../../parse/parseRelationship';
|
||||
import Word from '../../Word';
|
||||
|
||||
export class Blip {
|
||||
embled?: Relationship;
|
@ -2,7 +2,7 @@
|
||||
* http://webapp.docx4java.org/OnlineDemo/ecma376/DrawingML/blipFill_2.html
|
||||
*/
|
||||
|
||||
import Word from '../../../Word';
|
||||
import Word from '../../Word';
|
||||
import {Blip} from './Blip';
|
||||
|
||||
export class BlipFill {
|
@ -2,8 +2,8 @@
|
||||
* 自定义形状
|
||||
*/
|
||||
|
||||
import Word from '../../../Word';
|
||||
import {parseShape} from '../../../parse/parseShape';
|
||||
import Word from '../../Word';
|
||||
import {parseShape} from '../../parse/parseShape';
|
||||
import {Shape} from './Shape';
|
||||
|
||||
export class CustomGeom {
|
@ -2,16 +2,16 @@
|
||||
* 目前图片和 textbox 都会依赖这个
|
||||
*/
|
||||
|
||||
import {LengthUsage, convertLength} from './../../../parse/parseSize';
|
||||
import {CSSStyle} from './../../Style';
|
||||
import {LengthUsage, convertLength} from '../../parse/parseSize';
|
||||
import {CSSStyle} from './../Style';
|
||||
|
||||
import {getAttrBoolean, getAttrNumber, getValBoolean} from '../../../OpenXML';
|
||||
import Word from '../../../Word';
|
||||
import {getAttrBoolean, getAttrNumber, getValBoolean} from '../../OpenXML';
|
||||
import Word from '../../Word';
|
||||
import {Pic} from './Pic';
|
||||
import {parseSize} from '../../../parse/parseSize';
|
||||
import {ST_RelFromH, ST_RelFromV} from '../../Types';
|
||||
import {WPS} from '../wps/WPS';
|
||||
import {behindIndex} from '../../../render/zindex';
|
||||
import {parseSize} from '../../parse/parseSize';
|
||||
import {ST_RelFromH, ST_RelFromV} from '../Types';
|
||||
import {WPS} from '../word/wps/WPS';
|
||||
import {Diagram} from './diagram/Diagram';
|
||||
|
||||
/**
|
||||
* drawing 在文档中的位置,目前有两种情况,child 和 anchor
|
||||
@ -47,6 +47,8 @@ export class Drawing {
|
||||
pic?: Pic;
|
||||
// 主要用于文本框
|
||||
wps?: WPS;
|
||||
// 主要用于 smartArt
|
||||
diagram?: ConstrainDOMStringParameters;
|
||||
// drawing 的位置配置
|
||||
position: Position = Position.inline;
|
||||
// 如果是 anchor,描述具体配置
|
||||
@ -169,6 +171,12 @@ export class Drawing {
|
||||
drawing.wps = WPS.fromXML(word, graphicDataChild);
|
||||
break;
|
||||
|
||||
case 'dgm:relIds':
|
||||
// 这个是 diagram 的关系
|
||||
// http://webapp.docx4java.org/OnlineDemo/ecma376/DrawingML/relIds.html
|
||||
drawing.diagram = Diagram.fromXML(word, graphicDataChild);
|
||||
break;
|
||||
|
||||
default:
|
||||
console.warn(
|
||||
'unknown graphicData child tag',
|
@ -1,9 +1,9 @@
|
||||
/**
|
||||
* 形状
|
||||
*/
|
||||
import {ST_ShapeType} from '../../Types';
|
||||
import Word from '../../../Word';
|
||||
import {parseShapeGuide} from '../../../parse/parseShape';
|
||||
import {ST_ShapeType} from '../Types';
|
||||
import Word from '../../Word';
|
||||
import {parseShapeGuide} from '../../parse/parseShape';
|
||||
import {ShapeGuide} from './Shape';
|
||||
|
||||
export class Geom {
|
@ -1,4 +1,4 @@
|
||||
import {ST_PathFillMode} from '../../Types';
|
||||
import {ST_PathFillMode} from '../Types';
|
||||
|
||||
export interface IPath {
|
||||
type: 'moveTo' | 'lnTo' | 'arcTo' | 'cubicBezTo' | 'quadBezTo' | 'close';
|
44
packages/ooxml-viewer/src/openxml/drawing/Pic.ts
Normal file
44
packages/ooxml-viewer/src/openxml/drawing/Pic.ts
Normal file
@ -0,0 +1,44 @@
|
||||
import {getAttrBoolean} from '../../OpenXML';
|
||||
import Word from '../../Word';
|
||||
import {BlipFill} from './BlipFill';
|
||||
import {ShapePr} from './ShapeProperties';
|
||||
|
||||
export class Pic {
|
||||
blipFill: BlipFill;
|
||||
spPr: ShapePr;
|
||||
|
||||
/**
|
||||
* 替换图片的地址
|
||||
*/
|
||||
alt?: string;
|
||||
|
||||
/**
|
||||
* 这个是前面变量替换后,系统自动生成的 alt 地址,用于循环里的变量
|
||||
*/
|
||||
altVar?: string;
|
||||
|
||||
static fromXML(word: Word, element?: Element | null): Pic {
|
||||
const pic = new Pic();
|
||||
|
||||
const cNvPr = element?.getElementsByTagName('pic:cNvPr').item(0);
|
||||
if (cNvPr) {
|
||||
pic.alt = cNvPr.getAttribute('descr') || '';
|
||||
pic.altVar = cNvPr.getAttribute('descrVar') || '';
|
||||
|
||||
const hidden = getAttrBoolean(cNvPr, 'hidden', false);
|
||||
if (hidden) {
|
||||
return pic;
|
||||
}
|
||||
}
|
||||
|
||||
pic.blipFill = BlipFill.fromXML(
|
||||
word,
|
||||
element?.getElementsByTagName('pic:blipFill').item(0)
|
||||
);
|
||||
pic.spPr = ShapePr.fromXML(
|
||||
word,
|
||||
element?.getElementsByTagName('pic:spPr').item(0)
|
||||
);
|
||||
return pic;
|
||||
}
|
||||
}
|
@ -2,13 +2,12 @@
|
||||
* http://webapp.docx4java.org/OnlineDemo/ecma376/DrawingML/spPr_2.html
|
||||
*/
|
||||
|
||||
import {ST_PresetLineDashVal, ST_ShapeType} from '../../Types';
|
||||
import Word from '../../../Word';
|
||||
import {ST_PresetLineDashVal, ST_ShapeType} from '../Types';
|
||||
import Word from '../../Word';
|
||||
import {Transform} from './Transform';
|
||||
import {CSSStyle} from './../../Style';
|
||||
import {parseSize, LengthUsage} from '../../../parse/parseSize';
|
||||
import {parseSize, LengthUsage} from '../../parse/parseSize';
|
||||
import {Geom} from './Geom';
|
||||
import {parseChildColor} from '../../../parse/parseChildColor';
|
||||
import {parseChildColor} from '../../parse/parseChildColor';
|
||||
import {CustomGeom} from './CustomGeom';
|
||||
|
||||
function prstDashToCSSBorderType(prstDash: ST_PresetLineDashVal) {
|
@ -2,8 +2,8 @@
|
||||
* http://webapp.docx4java.org/OnlineDemo/ecma376/DrawingML/xfrm_2.html
|
||||
*/
|
||||
|
||||
import {convertAngle, LengthUsage, parseSize} from '../../../parse/parseSize';
|
||||
import Word from '../../../Word';
|
||||
import {convertAngle, LengthUsage, parseSize} from '../../parse/parseSize';
|
||||
import Word from '../../Word';
|
||||
|
||||
export interface Off {
|
||||
x: string;
|
23
packages/ooxml-viewer/src/openxml/drawing/diagram/Diagram.ts
Normal file
23
packages/ooxml-viewer/src/openxml/drawing/diagram/Diagram.ts
Normal file
@ -0,0 +1,23 @@
|
||||
/**
|
||||
* 图形,这块没啥文档说明,大部分是靠猜的
|
||||
*/
|
||||
|
||||
import Word from '../../../Word';
|
||||
|
||||
export class Diagram {
|
||||
// 这里的输入是 dgm:relIds 元素
|
||||
static fromXML(word: Word, relidsElement: Element) {
|
||||
const diagram = new Diagram();
|
||||
const dmId = relidsElement.getAttribute('r:dm');
|
||||
if (dmId) {
|
||||
const dmRel = word.getDocumentRels(dmId);
|
||||
if (dmRel) {
|
||||
// 对应的就是 digrams/data1.xml 文件
|
||||
const dm = word.loadWordRelXML(dmRel);
|
||||
console.log(dm);
|
||||
}
|
||||
}
|
||||
|
||||
return diagram;
|
||||
}
|
||||
}
|
1
packages/ooxml-viewer/src/openxml/drawing/diagram/Sp.ts
Normal file
1
packages/ooxml-viewer/src/openxml/drawing/diagram/Sp.ts
Normal file
@ -0,0 +1 @@
|
||||
export class Sp {}
|
@ -0,0 +1,5 @@
|
||||
/**
|
||||
* Diagram 里的 spTree
|
||||
*/
|
||||
|
||||
export class SpTree {}
|
@ -4,9 +4,9 @@
|
||||
* https://wiki.documentfoundation.org/Development/Improve_handles_of_DrawingML_shapes
|
||||
*/
|
||||
|
||||
import {Color} from '../../../../util/color';
|
||||
import {createSVGElement} from '../../../../util/dom';
|
||||
import {WPSStyle} from '../../wps/WPSStyle';
|
||||
import {Color} from '../../../util/color';
|
||||
import {createSVGElement} from '../../../util/dom';
|
||||
import {WPSStyle} from '../../word/wps/WPSStyle';
|
||||
import {Shape, ShapeGuide} from '../Shape';
|
||||
import {ShapePr} from '../ShapeProperties';
|
||||
import {evalFmla} from './formulas';
|
@ -3,7 +3,7 @@ import {parsePr} from '../../parse/parsePr';
|
||||
import Word from '../../Word';
|
||||
import {ST_FldCharType, ST_VerticalAlignRun} from '../Types';
|
||||
import {Break} from './Break';
|
||||
import {Drawing} from './drawing/Drawing';
|
||||
import {Drawing} from '../drawing/Drawing';
|
||||
import {InstrText} from './InstrText';
|
||||
import {NoBreakHyphen} from './NoBreakHyphen';
|
||||
import {Pict} from './Pict';
|
||||
|
@ -1,21 +0,0 @@
|
||||
import Word from '../../../Word';
|
||||
import {BlipFill} from './BlipFill';
|
||||
import {ShapePr} from './ShapeProperties';
|
||||
|
||||
export class Pic {
|
||||
blipFill: BlipFill;
|
||||
spPr: ShapePr;
|
||||
|
||||
static fromXML(word: Word, element?: Element | null): Pic {
|
||||
const pic = new Pic();
|
||||
pic.blipFill = BlipFill.fromXML(
|
||||
word,
|
||||
element?.getElementsByTagName('pic:blipFill').item(0)
|
||||
);
|
||||
pic.spPr = ShapePr.fromXML(
|
||||
word,
|
||||
element?.getElementsByTagName('pic:spPr').item(0)
|
||||
);
|
||||
return pic;
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
import {Paragraph} from '../Paragraph';
|
||||
import {ShapePr} from '../drawing/ShapeProperties';
|
||||
import {ShapePr} from '../../drawing/ShapeProperties';
|
||||
/**
|
||||
* wps 指的是 wordprocessingShape,在 drawing 里 word 相关的 shape 定义
|
||||
* 目前主要是支持 textbox,
|
||||
|
@ -13,8 +13,8 @@ import {
|
||||
Path,
|
||||
IPath,
|
||||
PathPoint
|
||||
} from '../openxml/word/drawing/Path';
|
||||
import {Rect, Shape, ShapeGuide} from '../openxml/word/drawing/Shape';
|
||||
} from '../openxml/drawing/Path';
|
||||
import {Rect, Shape, ShapeGuide} from '../openxml/drawing/Shape';
|
||||
|
||||
export function parsePts(element: Element) {
|
||||
const pts: PathPoint[] = [];
|
||||
|
@ -1,7 +1,7 @@
|
||||
import {ShapePr} from '../openxml/word/drawing/ShapeProperties';
|
||||
import {shapeToSVG} from '../openxml/word/drawing/svg/shapeToSVG';
|
||||
import {ShapePr} from '../openxml/drawing/ShapeProperties';
|
||||
import {shapeToSVG} from '../openxml/drawing/svg/shapeToSVG';
|
||||
import {WPSStyle} from '../openxml/word/wps/WPSStyle';
|
||||
import {CustomGeom} from '../openxml/word/drawing/CustomGeom';
|
||||
import {CustomGeom} from '../openxml/drawing/CustomGeom';
|
||||
|
||||
export function renderCustGeom(
|
||||
geom: CustomGeom,
|
||||
|
@ -1,14 +1,13 @@
|
||||
import {Paragraph} from './../openxml/word/Paragraph';
|
||||
import Word from '../Word';
|
||||
import {Drawing} from '../openxml/word/drawing/Drawing';
|
||||
import {Pic} from '../openxml/word/drawing/Pic';
|
||||
import {Drawing} from '../openxml/drawing/Drawing';
|
||||
import {Pic} from '../openxml/drawing/Pic';
|
||||
import {appendChild, applyStyle} from '../util/dom';
|
||||
import renderParagraph from './renderParagraph';
|
||||
import renderTable from './renderTable';
|
||||
import {Table} from '../openxml/word/Table';
|
||||
import {renderGeom} from './renderGeom';
|
||||
import {renderCustGeom} from './renderCustGeom';
|
||||
import {fixAbsolutePosition} from './fixAbsolutePosition';
|
||||
|
||||
/**
|
||||
* 渲染图片
|
||||
@ -18,9 +17,20 @@ function renderPic(pic: Pic, word: Word, drawing: Drawing) {
|
||||
if (blip && blip.src) {
|
||||
const img = document.createElement('img') as HTMLImageElement;
|
||||
img.style.position = 'relative';
|
||||
|
||||
img.alt = pic.alt || '';
|
||||
img.src = blip.src;
|
||||
|
||||
if (pic.alt && word.renderOptions.enableVar) {
|
||||
if (pic.altVar) {
|
||||
img.src = pic.altVar;
|
||||
} else if (pic.alt.startsWith('{{')) {
|
||||
const src = word.replaceText(pic.alt);
|
||||
if (src) {
|
||||
img.src = src;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const xfrm = pic.spPr?.xfrm;
|
||||
|
||||
if (xfrm) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import {presetShape} from '../openxml/word/drawing/presetShape';
|
||||
import {Geom} from '../openxml/word/drawing/Geom';
|
||||
import {ShapePr} from '../openxml/word/drawing/ShapeProperties';
|
||||
import {shapeToSVG} from '../openxml/word/drawing/svg/shapeToSVG';
|
||||
import {presetShape} from '../openxml/drawing/presetShape';
|
||||
import {Geom} from '../openxml/drawing/Geom';
|
||||
import {ShapePr} from '../openxml/drawing/ShapeProperties';
|
||||
import {shapeToSVG} from '../openxml/drawing/svg/shapeToSVG';
|
||||
import {WPSStyle} from '../openxml/word/wps/WPSStyle';
|
||||
|
||||
export function renderGeom(
|
||||
|
@ -7,7 +7,7 @@ import {appendChild, createElement, applyStyle} from '../util/dom';
|
||||
import Word from '../Word';
|
||||
import {Run, Text} from '../openxml/word/Run';
|
||||
import {Break} from '../openxml/word/Break';
|
||||
import {Drawing} from '../openxml/word/drawing/Drawing';
|
||||
import {Drawing} from '../openxml/drawing/Drawing';
|
||||
import {renderDrawing} from './renderDrawing';
|
||||
import {setElementStyle} from './setElementStyle';
|
||||
import {Tab} from '../openxml/word/Tab';
|
||||
|
@ -11,12 +11,29 @@ import {createObject} from './createObject';
|
||||
*/
|
||||
export function replaceT(word: Word, t: Element, data: any) {
|
||||
let text = t.textContent || '';
|
||||
t.textContent = replaceText(word, text, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 替换变量文本
|
||||
*/
|
||||
function replaceText(word: Word, text: string, data: any) {
|
||||
const evalVar = word.renderOptions.evalVar;
|
||||
if (text.startsWith('{{')) {
|
||||
text = text.replace(/^{{/g, '').replace(/}}$/g, '');
|
||||
const result = String(evalVar(text, data)) || '';
|
||||
t.textContent = result;
|
||||
const result = evalVar(text, data);
|
||||
if (result !== undefined && result !== null) {
|
||||
return String(result);
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
function replaceAlt(word: Word, cNvPr: Element, data: any) {
|
||||
const alt = cNvPr.getAttribute('descr') || '';
|
||||
cNvPr.setAttribute('descrVar', replaceText(word, alt, data));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -68,6 +85,11 @@ function replaceTableRow(word: Word, tr: Element) {
|
||||
replaceT(word, t, rowData);
|
||||
}
|
||||
|
||||
// 替换图片里的变量
|
||||
for (const cNvPr of newTr.getElementsByTagName('pic:cNvPr')) {
|
||||
replaceAlt(word, cNvPr, rowData);
|
||||
}
|
||||
|
||||
table.appendChild(newTr);
|
||||
}
|
||||
// 删除原来的行
|
||||
@ -110,7 +132,6 @@ function removeAllAttr(node: Element) {
|
||||
* 替换表格,目前只支持行
|
||||
*/
|
||||
function replaceTable(word: Word, documentData: Document) {
|
||||
const evalVar = word.renderOptions.evalVar;
|
||||
const trs = [].slice.call(documentData.getElementsByTagName('w:tr'));
|
||||
for (const tr of trs) {
|
||||
replaceTableRow(word, tr);
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
import {readFileSync, writeFileSync} from 'fs';
|
||||
import {parseXML} from '../src/util/xml';
|
||||
import {Shape} from '../src/openxml/word/drawing/Shape';
|
||||
import {Shape} from '../src/openxml/drawing/Shape';
|
||||
import {parseShape} from '../src/parse/parseShape';
|
||||
|
||||
import jsdom from 'jsdom';
|
||||
|
Loading…
Reference in New Issue
Block a user