@dev-to/react-plugin 0.2.0 → 0.4.0
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/dist/debugHtml.d.ts.map +1 -1
- package/dist/debugTools.d.ts.map +1 -1
- package/dist/index.js +231 -49
- package/dist/loaderUmdWrapper.d.ts +1 -0
- package/dist/loaderUmdWrapper.d.ts.map +1 -1
- package/package.json +2 -2
package/dist/debugHtml.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"debugHtml.d.ts","sourceRoot":"","sources":["../src/debugHtml.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAEhE,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,OAAO,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,KAAK,EAAE,OAAO,CAAA;CACf;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,iBAAiB,CAAA;IACxB,uBAAuB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/C,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACrC,KAAK,EAAE,WAAW,CAAA;IAClB,gBAAgB,EAAE,oBAAoB,CAAA;IACtC,gBAAgB,EAAE,MAAM,EAAE,CAAA;IAC1B,UAAU,EAAE,MAAM,GAAG,SAAS,CAAA;IAC9B,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,qBAAqB,
|
|
1
|
+
{"version":3,"file":"debugHtml.d.ts","sourceRoot":"","sources":["../src/debugHtml.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAEhE,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,OAAO,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,KAAK,EAAE,OAAO,CAAA;CACf;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,iBAAiB,CAAA;IACxB,uBAAuB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/C,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACrC,KAAK,EAAE,WAAW,CAAA;IAClB,gBAAgB,EAAE,oBAAoB,CAAA;IACtC,gBAAgB,EAAE,MAAM,EAAE,CAAA;IAC1B,UAAU,EAAE,MAAM,GAAG,SAAS,CAAA;IAC9B,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,qBAAqB,UAskB5D"}
|
package/dist/debugTools.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"debugTools.d.ts","sourceRoot":"","sources":["../src/debugTools.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"debugTools.d.ts","sourceRoot":"","sources":["../src/debugTools.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,MAAM,CAAA;AAEzC,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,0BAA0B,EAAE,MAAM,YAAY,CAAA;AAG/H,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,cAAc,CAAA;IACxB,KAAK,EAAE,WAAW,CAAA;IAClB,KAAK,EAAE,iBAAiB,CAAA;IACxB,cAAc,EAAE,0BAA0B,CAAA;IAC1C,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,CAAC,EAAE,OAAO,CAAA;CACf;AAqFD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,EAAE,iBAAiB,EAAE,KAAK,EAAE,iBAAiB,QAwUxG"}
|
package/dist/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import node_path from "node:path";
|
|
|
4
4
|
import picocolors from "picocolors";
|
|
5
5
|
import { mergeConfig } from "vite";
|
|
6
6
|
import { exec } from "node:child_process";
|
|
7
|
+
import { fileURLToPath } from "node:url";
|
|
7
8
|
import node_os from "node:os";
|
|
8
9
|
import typescript from "typescript";
|
|
9
10
|
const PLUGIN_NAME = DEV_TO_REACT_NAMESPACE;
|
|
@@ -237,17 +238,14 @@ function renderDebugHtml(params) {
|
|
|
237
238
|
|
|
238
239
|
${hasConfig ? `
|
|
239
240
|
<table>
|
|
240
|
-
<thead><tr><th>组件名称 <small class="muted">(Component Name)</small></th><th>映射入口 <small class="muted">(Short Path)</small></th></tr></thead>
|
|
241
|
+
<thead><tr><th>组件名称 <small class="muted">(Component Name)</small></th><th>映射入口 <small class="muted">(Short Path)</small></th><th>包装地址 <small class="muted">(UMD Wrapper)</small></th></tr></thead>
|
|
241
242
|
<tbody>
|
|
242
243
|
${Object.entries(resolvedDevComponentMap).map(([name, entry])=>{
|
|
243
244
|
const abs = entryPathMap[name];
|
|
244
245
|
const displayPath = abs ? getShortPath(abs) : entry;
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
${abs ? `<a href="${toVsCodeUrl(abs)}" class="link-code" title="点击在 IDE 中打开"><code>${escapeHtml(displayPath)}</code></a>` : `<code>${escapeHtml(entry)}</code>`}
|
|
249
|
-
</td>
|
|
250
|
-
</tr>`;
|
|
246
|
+
const wrapperUrl = (originCandidates[0] || 'http://localhost:5173') + '/__dev_to_react__/loader/' + name + '.js';
|
|
247
|
+
const entryHtml = abs ? '<a href="' + toVsCodeUrl(abs) + '" class="link-code" title="点击在 IDE 中打开"><code>' + escapeHtml(displayPath) + '</code></a>' : '<code>' + escapeHtml(entry) + '</code>';
|
|
248
|
+
return '<tr><td><code class="code-name">' + name + "</code></td><td>" + entryHtml + '</td><td><div style="display: flex; align-items: center; gap: 6px;"><code style="flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px;">' + escapeHtml(wrapperUrl) + '</code><button class="copy-wrapper-btn" data-url="' + wrapperUrl + '" style="padding: 2px 8px; font-size: 11px; border: 1px solid var(--b); background: #fff; border-radius: 4px; cursor: pointer; color: var(--t); transition: .2s;" title="复制包装地址">\uD83D\uDCCB</button></div></td></tr>';
|
|
251
249
|
}).join('')}
|
|
252
250
|
</tbody>
|
|
253
251
|
</table>
|
|
@@ -329,6 +327,56 @@ reactHmrHostPlugin(<span class="str">'Demo'</span>, { open: <span class="kw">tru
|
|
|
329
327
|
</details>
|
|
330
328
|
</div>
|
|
331
329
|
|
|
330
|
+
<div class="card">
|
|
331
|
+
<h3>🎁 UMD 动态包装器 (Auto-Generated Wrapper)</h3>
|
|
332
|
+
<p class="muted">无需额外配置,每个组件都自动生成一个轻量级 UMD 包装器,可直接在无 React 框架支持的宿主环境中使用。</p>
|
|
333
|
+
|
|
334
|
+
<div class="info-grid">
|
|
335
|
+
<div class="info-label">端点:</div>
|
|
336
|
+
<div class="info-value"><code>/__dev_to_react__/loader/{ComponentName}.js</code></div>
|
|
337
|
+
<div class="info-label">作用:</div>
|
|
338
|
+
<div class="info-value">自动将组件导出为 React 组件实例,无需宿主集成 @dev-to/react-loader</div>
|
|
339
|
+
<div class="info-label">依赖:</div>
|
|
340
|
+
<div class="info-value"><code>react</code> & <code>react-dom@18</code> (CDN 或本地)</div>
|
|
341
|
+
</div>
|
|
342
|
+
|
|
343
|
+
<details>
|
|
344
|
+
<summary>包装器工作原理与集成示例</summary>
|
|
345
|
+
<div style="margin-top: 12px;">
|
|
346
|
+
<h4 style="color: var(--t); font-size: 14px; margin-top: 0; margin-bottom: 8px;">🔧 什么是包装器?</h4>
|
|
347
|
+
<p class="muted" style="margin-bottom: 12px;">
|
|
348
|
+
包装器是一个自动生成的 UMD 模块,它包装了原始的 render 函数并导出为 React 组件。
|
|
349
|
+
这样,无论宿主是否集成了 ReactLoader,都能直接作为 React 组件使用。
|
|
350
|
+
</p>
|
|
351
|
+
|
|
352
|
+
<h4 style="color: var(--t); font-size: 14px; margin-top: 16px; margin-bottom: 8px;">📖 集成方式</h4>
|
|
353
|
+
<pre style="font-size: 12px; line-height: 1.7;">
|
|
354
|
+
<span class="cmt">// 1. 加载 React 和 ReactDOM</span>
|
|
355
|
+
<span class="kw"><script></span> <span class="kw">src</span>=<span class="str">"https://unpkg.com/react@18/umd/react.production.min.js"</span> <span class="kw"></script></span>
|
|
356
|
+
<span class="kw"><script></span> <span class="kw">src</span>=<span class="str">"https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"</span> <span class="kw"></script></span>
|
|
357
|
+
|
|
358
|
+
<span class="cmt">// 2. 加载包装器脚本</span>
|
|
359
|
+
<span class="kw"><script></span> <span class="kw">src</span>=<span class="str">"\${originCandidates[0] || 'http://localhost:5173'}/__dev_to_react__/loader/{ComponentName}.js"</span> <span class="kw"></script></span>
|
|
360
|
+
|
|
361
|
+
<span class="cmt">// 3. 直接作为 React 组件使用</span>
|
|
362
|
+
<span class="kw">const</span> root = ReactDOM.createRoot(document.getElementById(<span class="str">'app'</span>));
|
|
363
|
+
root.render(React.createElement(window.ComponentName, { prop1: <span class="str">'value1'</span> }));
|
|
364
|
+
|
|
365
|
+
<span class="cmt">// 或在宿主 React 组件中使用</span>
|
|
366
|
+
<span class="kw">const</span> Component = window.ComponentName;
|
|
367
|
+
<span class="kw"><></span><Component prop1=<span class="str">"value1"</span> /><span class="kw"></></span></pre>
|
|
368
|
+
|
|
369
|
+
<h4 style="color: var(--t); font-size: 14px; margin-top: 16px; margin-bottom: 8px;">⚡ 关键特性</h4>
|
|
370
|
+
<ul class="muted" style="margin: 8px 0; padding-left: 20px;">
|
|
371
|
+
<li><b>零配置</b>:自动为每个组件生成包装器,无需手动编写</li>
|
|
372
|
+
<li><b>兼容现有宿主</b>:支持 CommonJS、AMD、浏览器全局三种模式</li>
|
|
373
|
+
<li><b>自动依赖管理</b>:若未加载 React,包装器会自动从 CDN 加载(可配置)</li>
|
|
374
|
+
<li><b>轻量级</b>:仅包含加载逻辑,核心渲染由 ReactLoader 负责</li>
|
|
375
|
+
</ul>
|
|
376
|
+
</div>
|
|
377
|
+
</details>
|
|
378
|
+
</div>
|
|
379
|
+
|
|
332
380
|
<div class="card">
|
|
333
381
|
<h3>📦 构建与部署</h3>
|
|
334
382
|
<p class="muted">执行 <code>vite build --mode lib</code> 将组件打包为 UMD 格式以供发布。</p>
|
|
@@ -467,6 +515,27 @@ CSS: <span class="str">dist/<name>/<name>.css</span></pre>
|
|
|
467
515
|
setTimeout(() => { copyFullBtn.textContent = '复制原始命令'; }, 2000);
|
|
468
516
|
});
|
|
469
517
|
|
|
518
|
+
// 绑定包装地址复制按钮事件
|
|
519
|
+
document.querySelectorAll('.copy-wrapper-btn').forEach(btn => {
|
|
520
|
+
btn.onclick = (e) => {
|
|
521
|
+
e.preventDefault();
|
|
522
|
+
const url = btn.getAttribute('data-url');
|
|
523
|
+
copy(url, () => {
|
|
524
|
+
const originalText = btn.textContent;
|
|
525
|
+
btn.textContent = '✓';
|
|
526
|
+
btn.style.borderColor = '#10b981';
|
|
527
|
+
btn.style.color = '#10b981';
|
|
528
|
+
setTimeout(() => {
|
|
529
|
+
btn.textContent = originalText;
|
|
530
|
+
btn.style.borderColor = '';
|
|
531
|
+
btn.style.color = '';
|
|
532
|
+
}, 1500);
|
|
533
|
+
});
|
|
534
|
+
};
|
|
535
|
+
btn.onmouseover = () => { btn.style.borderColor = 'var(--p)'; btn.style.color = 'var(--p)'; };
|
|
536
|
+
btn.onmouseout = () => { btn.style.borderColor = ''; btn.style.color = ''; };
|
|
537
|
+
});
|
|
538
|
+
|
|
470
539
|
const serverActualPort = ${'number' == typeof actualPort ? actualPort : 'null'};
|
|
471
540
|
document.getElementById('actualPortDisplay').textContent = serverActualPort || location.port || '-';
|
|
472
541
|
})();
|
|
@@ -814,34 +883,49 @@ function generateLibBuildNextConfig(params) {
|
|
|
814
883
|
};
|
|
815
884
|
}
|
|
816
885
|
function createLoaderUmdWrapper(options) {
|
|
817
|
-
const { componentName, origin, contractEndpoint = constants_STABLE_CONTRACT_PATH } = options;
|
|
886
|
+
const { componentName, origin, contractEndpoint = constants_STABLE_CONTRACT_PATH, reactLoaderUrl = 'https://cdn.jsdelivr.net/npm/@dev-to/react-loader@latest/dist/index.umd.js' } = options;
|
|
818
887
|
const globalName = toSafeUmdName(componentName);
|
|
819
888
|
const code = `/**
|
|
820
889
|
* UMD Loader Wrapper for component: ${componentName}
|
|
821
890
|
* Global name: ${globalName}
|
|
822
891
|
* Generated by ${constants_PLUGIN_LOG_PREFIX}
|
|
823
892
|
*
|
|
824
|
-
* This wrapper
|
|
893
|
+
* This wrapper automatically exports a React component that can be used in any React environment.
|
|
894
|
+
* No need to manually integrate @dev-to/react-loader.
|
|
895
|
+
*
|
|
896
|
+
* ============= Quick Start =============
|
|
825
897
|
*
|
|
826
|
-
* Usage:
|
|
827
898
|
* 1. Load React and ReactDOM:
|
|
828
899
|
* <script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
|
|
829
900
|
* <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
|
|
830
901
|
*
|
|
831
|
-
* 2. Load
|
|
832
|
-
* <script src="https://cdn.jsdelivr.net/npm/@dev-to/react-loader@latest/dist/index.umd.js"></script>
|
|
833
|
-
*
|
|
834
|
-
* 3. Load this wrapper:
|
|
902
|
+
* 2. Load this wrapper:
|
|
835
903
|
* <script src="${origin}/__dev_to_react__/loader/${componentName}.js"></script>
|
|
836
904
|
*
|
|
837
|
-
*
|
|
838
|
-
*
|
|
839
|
-
*
|
|
840
|
-
*
|
|
841
|
-
*
|
|
842
|
-
*
|
|
843
|
-
*
|
|
844
|
-
*
|
|
905
|
+
* 3. Use as a React component:
|
|
906
|
+
*
|
|
907
|
+
* // Option A: Direct React rendering
|
|
908
|
+
* const Component = window.${globalName};
|
|
909
|
+
* const root = ReactDOM.createRoot(document.getElementById('app'));
|
|
910
|
+
* root.render(React.createElement(Component, { prop1: 'value1' }));
|
|
911
|
+
*
|
|
912
|
+
* // Option B: Use in JSX (if using Babel)
|
|
913
|
+
* const Component = window.${globalName};
|
|
914
|
+
* root.render(<Component prop1="value1" />);
|
|
915
|
+
*
|
|
916
|
+
* // Option C: Direct function call (legacy compatibility)
|
|
917
|
+
* window.${globalName}(document.getElementById('app'), { prop1: 'value1' })
|
|
918
|
+
* .then(root => console.log('Rendered'))
|
|
919
|
+
* .catch(err => console.error('Error:', err));
|
|
920
|
+
*
|
|
921
|
+
* ============= Features =============
|
|
922
|
+
* ✓ Zero configuration required
|
|
923
|
+
* ✓ Automatic React/ReactDOM detection
|
|
924
|
+
* ✓ Supports CommonJS, AMD, and global scope
|
|
925
|
+
* ✓ Auto-loads ReactLoader from CDN if needed
|
|
926
|
+
* ✓ Works in any React environment
|
|
927
|
+
*
|
|
928
|
+
* Note: Make sure React v18+ and react-dom/client are available globally.
|
|
845
929
|
*/
|
|
846
930
|
(function (root, factory) {
|
|
847
931
|
if (typeof exports === 'object' && typeof module !== 'undefined') {
|
|
@@ -853,20 +937,65 @@ function createLoaderUmdWrapper(options) {
|
|
|
853
937
|
} else {
|
|
854
938
|
// Browser globals
|
|
855
939
|
var globalObj = typeof globalThis !== 'undefined' ? globalThis : (typeof self !== 'undefined' ? self : root);
|
|
856
|
-
|
|
940
|
+
var tempExports = {};
|
|
941
|
+
factory(tempExports, globalObj.React, globalObj.ReactDOM, globalObj.DevToReactLoader);
|
|
942
|
+
globalObj.${globalName} = tempExports.default;
|
|
857
943
|
}
|
|
858
944
|
})(this, function (exports, React, ReactDOM, ReactLoaderModule) {
|
|
859
945
|
'use strict';
|
|
860
946
|
|
|
861
|
-
|
|
862
|
-
var
|
|
947
|
+
var ReactLoader = null;
|
|
948
|
+
var loadingPromise = null;
|
|
949
|
+
|
|
950
|
+
// Helper function to load a script dynamically
|
|
951
|
+
function loadScript(src) {
|
|
952
|
+
return new Promise(function(resolve, reject) {
|
|
953
|
+
var script = document.createElement('script');
|
|
954
|
+
script.src = src;
|
|
955
|
+
script.onload = resolve;
|
|
956
|
+
script.onerror = reject;
|
|
957
|
+
document.head.appendChild(script);
|
|
958
|
+
});
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
// Helper function to ensure ReactLoader is loaded
|
|
962
|
+
function ensureReactLoaderLoaded() {
|
|
963
|
+
if (ReactLoader) {
|
|
964
|
+
return Promise.resolve();
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
if (!loadingPromise) {
|
|
968
|
+
loadingPromise = (function() {
|
|
969
|
+
// First, try to get ReactLoader from the global scope
|
|
970
|
+
if (typeof window !== 'undefined' && window.DevToReactLoader && window.DevToReactLoader.ReactLoader) {
|
|
971
|
+
ReactLoader = window.DevToReactLoader.ReactLoader;
|
|
972
|
+
return Promise.resolve();
|
|
973
|
+
}
|
|
863
974
|
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
975
|
+
// If not available, load it from URL
|
|
976
|
+
console.log('${constants_PLUGIN_LOG_PREFIX} Loading @dev-to/react-loader...');
|
|
977
|
+
return loadScript(${JSON.stringify(reactLoaderUrl)})
|
|
978
|
+
.then(function() {
|
|
979
|
+
if (typeof window !== 'undefined' && window.DevToReactLoader && window.DevToReactLoader.ReactLoader) {
|
|
980
|
+
ReactLoader = window.DevToReactLoader.ReactLoader;
|
|
981
|
+
console.log('${constants_PLUGIN_LOG_PREFIX} ReactLoader loaded successfully');
|
|
982
|
+
} else {
|
|
983
|
+
throw new Error('${constants_PLUGIN_LOG_PREFIX} ReactLoader not found after loading');
|
|
984
|
+
}
|
|
985
|
+
})
|
|
986
|
+
.catch(function(error) {
|
|
987
|
+
console.error('${constants_PLUGIN_LOG_PREFIX} Failed to load ReactLoader:', error);
|
|
988
|
+
throw error;
|
|
989
|
+
});
|
|
990
|
+
})();
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
return loadingPromise;
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
// Try to get ReactLoader from the module if available
|
|
997
|
+
if (ReactLoaderModule && ReactLoaderModule.ReactLoader) {
|
|
998
|
+
ReactLoader = ReactLoaderModule.ReactLoader;
|
|
870
999
|
}
|
|
871
1000
|
|
|
872
1001
|
// Component configuration
|
|
@@ -892,28 +1021,59 @@ function createLoaderUmdWrapper(options) {
|
|
|
892
1021
|
throw new Error('${constants_PLUGIN_LOG_PREFIX} ReactDOM is not loaded');
|
|
893
1022
|
}
|
|
894
1023
|
|
|
895
|
-
//
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
1024
|
+
// Ensure ReactLoader is available before rendering
|
|
1025
|
+
return ensureReactLoaderLoaded().then(function() {
|
|
1026
|
+
if (!ReactLoader) {
|
|
1027
|
+
throw new Error('${constants_PLUGIN_LOG_PREFIX} ReactLoader initialization failed');
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
// Create ReactLoader component props
|
|
1031
|
+
var loaderProps = {
|
|
1032
|
+
origin: config.origin,
|
|
1033
|
+
name: config.name,
|
|
1034
|
+
contractEndpoint: config.contractEndpoint,
|
|
1035
|
+
componentProps: componentProps || {}
|
|
1036
|
+
};
|
|
902
1037
|
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
1038
|
+
// Render using ReactLoader
|
|
1039
|
+
var root = ReactDOM.createRoot(targetElement);
|
|
1040
|
+
root.render(React.createElement(ReactLoader, loaderProps));
|
|
906
1041
|
|
|
907
|
-
|
|
1042
|
+
return root;
|
|
1043
|
+
});
|
|
908
1044
|
}
|
|
909
1045
|
|
|
910
|
-
//
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
1046
|
+
// Create a React component wrapper for the render function
|
|
1047
|
+
function ComponentWrapper(props) {
|
|
1048
|
+
var containerRef = React.useRef(null);
|
|
1049
|
+
var isFirstRender = React.useRef(true);
|
|
914
1050
|
|
|
915
|
-
|
|
916
|
-
|
|
1051
|
+
React.useEffect(function() {
|
|
1052
|
+
if (!containerRef.current) return;
|
|
1053
|
+
|
|
1054
|
+
render(containerRef.current, props).catch(function(err) {
|
|
1055
|
+
console.error('${constants_PLUGIN_LOG_PREFIX} Failed to render ${componentName}:', err);
|
|
1056
|
+
console.error('${constants_PLUGIN_LOG_PREFIX} Props:', props);
|
|
1057
|
+
});
|
|
1058
|
+
|
|
1059
|
+
if (isFirstRender.current) {
|
|
1060
|
+
isFirstRender.current = false;
|
|
1061
|
+
if (typeof console !== 'undefined' && console.info) {
|
|
1062
|
+
console.info(
|
|
1063
|
+
'%c${constants_PLUGIN_LOG_PREFIX}%c Successfully loaded and rendered component: %c${componentName}',
|
|
1064
|
+
'color: #10b981; font-weight: bold;',
|
|
1065
|
+
'color: #64748b;',
|
|
1066
|
+
'color: #3b82f6; font-weight: bold;'
|
|
1067
|
+
);
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
}, [props]);
|
|
1071
|
+
|
|
1072
|
+
return React.createElement('div', { ref: containerRef });
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
// Export the API
|
|
1076
|
+
exports.default = ComponentWrapper;
|
|
917
1077
|
});
|
|
918
1078
|
`;
|
|
919
1079
|
return code;
|
|
@@ -1113,6 +1273,27 @@ function installDebugTools(server, ctx, state) {
|
|
|
1113
1273
|
}, null, 2));
|
|
1114
1274
|
return;
|
|
1115
1275
|
}
|
|
1276
|
+
if (pathname === `${STABLE_BASE_PATH}/react-loader.js`) try {
|
|
1277
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
1278
|
+
const __dirname = node_path.dirname(__filename);
|
|
1279
|
+
const reactLoaderUmdPath = node_path.resolve(__dirname, '../../react-loader/dist/index.umd.js');
|
|
1280
|
+
if (node_fs.existsSync(reactLoaderUmdPath)) {
|
|
1281
|
+
const umdCode = node_fs.readFileSync(reactLoaderUmdPath, 'utf-8');
|
|
1282
|
+
res.statusCode = 200;
|
|
1283
|
+
res.setHeader('Content-Type', "application/javascript; charset=utf-8");
|
|
1284
|
+
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
1285
|
+
res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');
|
|
1286
|
+
res.end(umdCode);
|
|
1287
|
+
return;
|
|
1288
|
+
}
|
|
1289
|
+
res.statusCode = 404;
|
|
1290
|
+
res.end(`react-loader UMD not found at ${reactLoaderUmdPath}. Run 'pnpm build' in react-loader package.`);
|
|
1291
|
+
return;
|
|
1292
|
+
} catch (error) {
|
|
1293
|
+
res.statusCode = 500;
|
|
1294
|
+
res.end(`Error loading react-loader UMD: ${error}`);
|
|
1295
|
+
return;
|
|
1296
|
+
}
|
|
1116
1297
|
if (pathname.startsWith(STABLE_LOADER_BASE_PATH)) {
|
|
1117
1298
|
const loaderPathPattern = new RegExp(`^${STABLE_LOADER_BASE_PATH}/([^/]+)\\.js$`);
|
|
1118
1299
|
const match = pathname.match(loaderPathPattern);
|
|
@@ -1127,7 +1308,8 @@ function installDebugTools(server, ctx, state) {
|
|
|
1127
1308
|
const code = createLoaderUmdWrapper({
|
|
1128
1309
|
componentName,
|
|
1129
1310
|
origin,
|
|
1130
|
-
contractEndpoint: constants_STABLE_CONTRACT_PATH
|
|
1311
|
+
contractEndpoint: constants_STABLE_CONTRACT_PATH,
|
|
1312
|
+
reactLoaderUrl: `${origin}${STABLE_BASE_PATH}/react-loader.js`
|
|
1131
1313
|
});
|
|
1132
1314
|
res.statusCode = 200;
|
|
1133
1315
|
res.setHeader('Content-Type', "application/javascript; charset=utf-8");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loaderUmdWrapper.d.ts","sourceRoot":"","sources":["../src/loaderUmdWrapper.ts"],"names":[],"mappings":"AAGA,UAAU,6BAA6B;IACrC,aAAa,EAAE,MAAM,CAAA;IACrB,MAAM,EAAE,MAAM,CAAA;IACd,gBAAgB,CAAC,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"loaderUmdWrapper.d.ts","sourceRoot":"","sources":["../src/loaderUmdWrapper.ts"],"names":[],"mappings":"AAGA,UAAU,6BAA6B;IACrC,aAAa,EAAE,MAAM,CAAA;IACrB,MAAM,EAAE,MAAM,CAAA;IACd,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,6BAA6B,GAAG,MAAM,CA2MrF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dev-to/react-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"picocolors": "^1.1.0",
|
|
33
33
|
"typescript": "^5.4.5",
|
|
34
|
-
"@dev-to/react-shared": "0.1.
|
|
34
|
+
"@dev-to/react-shared": "0.1.2"
|
|
35
35
|
},
|
|
36
36
|
"scripts": {
|
|
37
37
|
"build": "rslib build",
|