create-dev-to 1.5.2 → 1.6.2
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/README.md +1 -1
- package/dist/index.js +472 -54
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -78,7 +78,7 @@ bunx create-dev-to
|
|
|
78
78
|
- **JavaScript** - 使用 JavaScript 的 React 项目
|
|
79
79
|
- **JavaScript + SWC** - 使用 SWC 编译的 JavaScript React 项目
|
|
80
80
|
|
|
81
|
-
创建完成后会自动在 `vite.config.*` 中注入 `@dev-to/react-plugin`(`devToReactPlugin()`)。
|
|
81
|
+
创建完成后会自动在 `vite.config.*` 中注入 `@dev-to/react-plugin`(`devToReactPlugin()`),并在 `package.json` 中加入 `build:lib`(`dev-to build`,等价于 `vite build --mode lib`)。
|
|
82
82
|
|
|
83
83
|
## 安装进度展示
|
|
84
84
|
|
package/dist/index.js
CHANGED
|
@@ -14,10 +14,10 @@ import { InstallLogger } from "./installLogger.js";
|
|
|
14
14
|
import { displayInstallSummary } from "./visualComponents.js";
|
|
15
15
|
const PACKAGE_MANAGERS = ["pnpm", "npm", "yarn", "bun"];
|
|
16
16
|
const __BUILD_INFO__ = {
|
|
17
|
-
commit: "
|
|
17
|
+
commit: "98fa359",
|
|
18
18
|
branch: "main",
|
|
19
|
-
buildTime: "2026-01-16
|
|
20
|
-
version: "1.
|
|
19
|
+
buildTime: "2026-01-16 17:32",
|
|
20
|
+
version: "1.6.2"
|
|
21
21
|
};
|
|
22
22
|
const FRAMEWORKS = [
|
|
23
23
|
{
|
|
@@ -558,13 +558,226 @@ function editFile(file, callback) {
|
|
|
558
558
|
const content = fs.readFileSync(file, "utf-8");
|
|
559
559
|
fs.writeFileSync(file, callback(content), "utf-8");
|
|
560
560
|
}
|
|
561
|
+
const DEVTO_LOGO_SVG = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128">
|
|
562
|
+
<rect width="128" height="128" rx="24" fill="#0d1117"/>
|
|
563
|
+
<text x="64" y="75" text-anchor="middle" dominant-baseline="middle" fill="#3fb950" font-family="system-ui, -apple-system, sans-serif" font-weight="700" font-size="125">\u0189</text>
|
|
564
|
+
</svg>
|
|
565
|
+
`;
|
|
566
|
+
function ensureDevtoLogo(root) {
|
|
567
|
+
const assetsDir = path.join(root, "src", "assets");
|
|
568
|
+
if (!fs.existsSync(assetsDir)) {
|
|
569
|
+
fs.mkdirSync(assetsDir, { recursive: true });
|
|
570
|
+
}
|
|
571
|
+
const logoPath = path.join(assetsDir, "devto.svg");
|
|
572
|
+
fs.writeFileSync(logoPath, DEVTO_LOGO_SVG, "utf-8");
|
|
573
|
+
}
|
|
574
|
+
function updateAppTemplate(root, componentName, isTs) {
|
|
575
|
+
const appPath = path.join(root, "src", `App.${isTs ? "tsx" : "jsx"}`);
|
|
576
|
+
if (!fs.existsSync(appPath)) {
|
|
577
|
+
return;
|
|
578
|
+
}
|
|
579
|
+
const appContent = `import './App.css'
|
|
580
|
+
import ${componentName} from './${componentName}/index'
|
|
581
|
+
|
|
582
|
+
export default function App() {
|
|
583
|
+
return (
|
|
584
|
+
<div className="app">
|
|
585
|
+
<header className="app-header">
|
|
586
|
+
<span className="eyebrow">dev-to template</span>
|
|
587
|
+
<h1>Component preview</h1>
|
|
588
|
+
<p className="subtitle">
|
|
589
|
+
Vite dev server with <code>@dev-to/react-plugin</code>
|
|
590
|
+
</p>
|
|
591
|
+
</header>
|
|
592
|
+
|
|
593
|
+
<section className="preview">
|
|
594
|
+
<div className="preview-inner">
|
|
595
|
+
<${componentName} />
|
|
596
|
+
</div>
|
|
597
|
+
</section>
|
|
598
|
+
|
|
599
|
+
</div>
|
|
600
|
+
)
|
|
601
|
+
}
|
|
602
|
+
`;
|
|
603
|
+
fs.writeFileSync(appPath, appContent, "utf-8");
|
|
604
|
+
const appCssPath = path.join(root, "src", "App.css");
|
|
605
|
+
const appCssContent = `#root {
|
|
606
|
+
max-width: 1100px;
|
|
607
|
+
margin: 0 auto;
|
|
608
|
+
padding: 32px 20px 40px;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
.app {
|
|
612
|
+
display: flex;
|
|
613
|
+
flex-direction: column;
|
|
614
|
+
align-items: center;
|
|
615
|
+
gap: 32px;
|
|
616
|
+
text-align: center;
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
.app-header {
|
|
620
|
+
max-width: 720px;
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
.app-header h1 {
|
|
624
|
+
margin: 4px 0 6px;
|
|
625
|
+
font-size: 34px;
|
|
626
|
+
line-height: 1.15;
|
|
627
|
+
text-wrap: balance;
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
.eyebrow {
|
|
631
|
+
display: inline-block;
|
|
632
|
+
font-size: 10px;
|
|
633
|
+
letter-spacing: 1.8px;
|
|
634
|
+
text-transform: uppercase;
|
|
635
|
+
color: rgba(255, 255, 255, 0.6);
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
.subtitle {
|
|
639
|
+
margin: 0;
|
|
640
|
+
font-size: 13px;
|
|
641
|
+
line-height: 1.5;
|
|
642
|
+
text-wrap: balance;
|
|
643
|
+
color: rgba(255, 255, 255, 0.72);
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
.preview {
|
|
647
|
+
width: min(960px, 100%);
|
|
648
|
+
padding: 1px;
|
|
649
|
+
border-radius: 26px;
|
|
650
|
+
background: linear-gradient(130deg, #22d3ee, #38bdf8 35%, #34d399 70%, #fbbf24);
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
.preview-inner {
|
|
654
|
+
border-radius: 25px;
|
|
655
|
+
padding: 28px 20px;
|
|
656
|
+
background: rgba(15, 23, 42, 0.85);
|
|
657
|
+
box-shadow: 0 20px 60px rgba(15, 23, 42, 0.35);
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
.app-footer {
|
|
661
|
+
margin: 0;
|
|
662
|
+
font-size: 12px;
|
|
663
|
+
text-wrap: balance;
|
|
664
|
+
color: rgba(255, 255, 255, 0.6);
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
code {
|
|
668
|
+
background: rgba(255, 255, 255, 0.12);
|
|
669
|
+
padding: 2px 6px;
|
|
670
|
+
border-radius: 6px;
|
|
671
|
+
font-size: 11px;
|
|
672
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New',
|
|
673
|
+
monospace;
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
@media (prefers-color-scheme: dark) {
|
|
677
|
+
.app-header h1 {
|
|
678
|
+
color: #f8fafc;
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
.preview-inner {
|
|
682
|
+
background: #0b1220;
|
|
683
|
+
border: 1px solid rgba(148, 163, 184, 0.18);
|
|
684
|
+
box-shadow: 0 18px 50px rgba(2, 6, 23, 0.65);
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
.subtitle {
|
|
688
|
+
color: rgba(226, 232, 240, 0.78);
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
code {
|
|
692
|
+
background: rgba(148, 163, 184, 0.16);
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
@media (prefers-color-scheme: light) {
|
|
697
|
+
.eyebrow {
|
|
698
|
+
color: #6b7280;
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
.subtitle {
|
|
702
|
+
color: #4b5563;
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
.preview-inner {
|
|
706
|
+
background: #ffffff;
|
|
707
|
+
box-shadow: 0 18px 40px rgba(15, 23, 42, 0.12);
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
.app-footer {
|
|
711
|
+
color: #6b7280;
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
code {
|
|
715
|
+
background: #e2e8f0;
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
@media (max-width: 640px) {
|
|
720
|
+
#root {
|
|
721
|
+
padding: 28px 16px 36px;
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
.preview-inner {
|
|
725
|
+
padding: 24px 16px;
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
.app-header h1 {
|
|
729
|
+
font-size: 30px;
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
@media (max-width: 360px) {
|
|
734
|
+
#root {
|
|
735
|
+
padding: 24px 12px 32px;
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
.app {
|
|
739
|
+
gap: 24px;
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
.app-header h1 {
|
|
743
|
+
font-size: 26px;
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
.eyebrow {
|
|
747
|
+
font-size: 9px;
|
|
748
|
+
letter-spacing: 1.4px;
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
.subtitle {
|
|
752
|
+
font-size: 12px;
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
.preview-inner {
|
|
756
|
+
padding: 20px 12px;
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
.app-footer {
|
|
760
|
+
font-size: 11px;
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
code {
|
|
764
|
+
font-size: 10px;
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
`;
|
|
768
|
+
fs.writeFileSync(appCssPath, appCssContent, "utf-8");
|
|
769
|
+
}
|
|
561
770
|
function createComponentFile(root, componentName, isTs) {
|
|
562
771
|
const componentDir = path.join(root, "src", componentName);
|
|
563
772
|
const componentFile = path.join(componentDir, `index.${isTs ? "tsx" : "jsx"}`);
|
|
564
773
|
if (!fs.existsSync(componentDir)) {
|
|
565
774
|
fs.mkdirSync(componentDir, { recursive: true });
|
|
566
775
|
}
|
|
776
|
+
const componentFileName = `index.${isTs ? "tsx" : "jsx"}`;
|
|
567
777
|
const componentContent = isTs ? `import { useState } from 'react'
|
|
778
|
+
import devtoLogo from '../assets/devto.svg'
|
|
779
|
+
import reactLogo from '../assets/react.svg'
|
|
780
|
+
import viteLogo from '/vite.svg'
|
|
568
781
|
import './index.css'
|
|
569
782
|
|
|
570
783
|
export interface ${componentName}Props {
|
|
@@ -573,110 +786,308 @@ export interface ${componentName}Props {
|
|
|
573
786
|
|
|
574
787
|
export default function ${componentName}(props: ${componentName}Props) {
|
|
575
788
|
const [count, setCount] = useState(0)
|
|
789
|
+
const title = props.title || '\u0189evTo + Vite + React'
|
|
576
790
|
|
|
577
791
|
return (
|
|
578
|
-
<div className="${componentName.toLowerCase()}-
|
|
579
|
-
<
|
|
580
|
-
|
|
792
|
+
<div className="${componentName.toLowerCase()}-component">
|
|
793
|
+
<div className="logo-row">
|
|
794
|
+
<a href="https://github.com/YangYongAn/dev-to" target="_blank" rel="noreferrer">
|
|
795
|
+
<img src={devtoLogo} className="logo devto" alt="dev-to logo" />
|
|
796
|
+
</a>
|
|
797
|
+
<a href="https://vitejs.dev" target="_blank" rel="noreferrer">
|
|
798
|
+
<img src={viteLogo} className="logo" alt="Vite logo" />
|
|
799
|
+
</a>
|
|
800
|
+
<a href="https://react.dev" target="_blank" rel="noreferrer">
|
|
801
|
+
<img src={reactLogo} className="logo react" alt="React logo" />
|
|
802
|
+
</a>
|
|
803
|
+
</div>
|
|
804
|
+
<h1>{title}</h1>
|
|
805
|
+
<p className="subtitle">
|
|
806
|
+
<span>Remote component served by</span>
|
|
807
|
+
<code>@dev-to/react-plugin</code>
|
|
808
|
+
</p>
|
|
809
|
+
<div className="counter-card">
|
|
581
810
|
<button onClick={() => setCount(count => count + 1)}>
|
|
582
811
|
count is {count}
|
|
583
812
|
</button>
|
|
584
813
|
<p>
|
|
585
|
-
Edit <code>src/${componentName}
|
|
814
|
+
Edit <code>src/${componentName}/${componentFileName}</code> to test HMR
|
|
586
815
|
</p>
|
|
587
816
|
</div>
|
|
588
|
-
<p className="
|
|
589
|
-
|
|
817
|
+
<p className="read-the-docs">
|
|
818
|
+
Click on the \u0189evTo, Vite, and React logos to learn more
|
|
590
819
|
</p>
|
|
591
820
|
</div>
|
|
592
821
|
)
|
|
593
822
|
}
|
|
594
823
|
` : `import { useState } from 'react'
|
|
824
|
+
import devtoLogo from '../assets/devto.svg'
|
|
825
|
+
import reactLogo from '../assets/react.svg'
|
|
826
|
+
import viteLogo from '/vite.svg'
|
|
595
827
|
import './index.css'
|
|
596
828
|
|
|
597
829
|
export default function ${componentName}(props) {
|
|
598
830
|
const [count, setCount] = useState(0)
|
|
831
|
+
const title = props.title || '\u0189evTo + Vite + React'
|
|
599
832
|
|
|
600
833
|
return (
|
|
601
|
-
<div className="${componentName.toLowerCase()}-
|
|
602
|
-
<
|
|
603
|
-
|
|
834
|
+
<div className="${componentName.toLowerCase()}-component">
|
|
835
|
+
<div className="logo-row">
|
|
836
|
+
<a href="https://github.com/YangYongAn/dev-to" target="_blank" rel="noreferrer">
|
|
837
|
+
<img src={devtoLogo} className="logo devto" alt="dev-to logo" />
|
|
838
|
+
</a>
|
|
839
|
+
<a href="https://vitejs.dev" target="_blank" rel="noreferrer">
|
|
840
|
+
<img src={viteLogo} className="logo" alt="Vite logo" />
|
|
841
|
+
</a>
|
|
842
|
+
<a href="https://react.dev" target="_blank" rel="noreferrer">
|
|
843
|
+
<img src={reactLogo} className="logo react" alt="React logo" />
|
|
844
|
+
</a>
|
|
845
|
+
</div>
|
|
846
|
+
<h1>{title}</h1>
|
|
847
|
+
<p className="subtitle">
|
|
848
|
+
<span>Remote component served by</span>
|
|
849
|
+
<code>@dev-to/react-plugin</code>
|
|
850
|
+
</p>
|
|
851
|
+
<div className="counter-card">
|
|
604
852
|
<button onClick={() => setCount(count => count + 1)}>
|
|
605
853
|
count is {count}
|
|
606
854
|
</button>
|
|
607
855
|
<p>
|
|
608
|
-
Edit <code>src/${componentName}
|
|
856
|
+
Edit <code>src/${componentName}/${componentFileName}</code> to test HMR
|
|
609
857
|
</p>
|
|
610
858
|
</div>
|
|
611
|
-
<p className="
|
|
612
|
-
|
|
859
|
+
<p className="read-the-docs">
|
|
860
|
+
Click on the \u0189evTo, Vite, and React logos to learn more
|
|
613
861
|
</p>
|
|
614
862
|
</div>
|
|
615
863
|
)
|
|
616
864
|
}
|
|
617
865
|
`;
|
|
618
|
-
const
|
|
619
|
-
|
|
866
|
+
const rootClass = `${componentName.toLowerCase()}-component`;
|
|
867
|
+
const styleContent = `.${rootClass} {
|
|
868
|
+
max-width: 720px;
|
|
620
869
|
margin: 0 auto;
|
|
621
|
-
padding:
|
|
870
|
+
padding: 20px 12px 28px;
|
|
622
871
|
text-align: center;
|
|
623
872
|
}
|
|
624
873
|
|
|
625
|
-
.${
|
|
626
|
-
|
|
874
|
+
.${rootClass} .logo-row {
|
|
875
|
+
display: flex;
|
|
876
|
+
flex-wrap: wrap;
|
|
877
|
+
align-items: center;
|
|
878
|
+
justify-content: center;
|
|
879
|
+
gap: 10px;
|
|
880
|
+
margin-bottom: 18px;
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
.${rootClass} .logo {
|
|
884
|
+
height: 48px;
|
|
885
|
+
padding: 0;
|
|
886
|
+
will-change: filter, transform;
|
|
887
|
+
transition: transform 0.25s ease, filter 0.25s ease;
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
.${rootClass} .logo.devto {
|
|
891
|
+
border-radius: 14px;
|
|
892
|
+
background: rgba(15, 23, 42, 0.9);
|
|
893
|
+
box-shadow: 0 10px 30px rgba(15, 23, 42, 0.35);
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
.${rootClass} .logo:hover {
|
|
897
|
+
filter: drop-shadow(0 0 18px rgba(56, 189, 248, 0.6));
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
.${rootClass} .logo.react:hover {
|
|
901
|
+
filter: drop-shadow(0 0 18px rgba(97, 218, 251, 0.65));
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
.${rootClass} h1 {
|
|
905
|
+
margin: 12px 0 6px;
|
|
906
|
+
font-size: 28px;
|
|
627
907
|
line-height: 1.1;
|
|
628
|
-
|
|
908
|
+
white-space: nowrap;
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
.${rootClass} .subtitle {
|
|
912
|
+
margin: 0 auto 18px;
|
|
913
|
+
max-width: 500px;
|
|
914
|
+
font-size: 13px;
|
|
915
|
+
line-height: 1.5;
|
|
916
|
+
text-wrap: balance;
|
|
917
|
+
color: rgba(255, 255, 255, 0.72);
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
.${rootClass} .subtitle span {
|
|
921
|
+
display: block;
|
|
629
922
|
}
|
|
630
923
|
|
|
631
|
-
.
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
border-radius: 8px;
|
|
635
|
-
margin: 2rem 0;
|
|
924
|
+
.${rootClass} .subtitle code {
|
|
925
|
+
display: inline-block;
|
|
926
|
+
margin-top: 4px;
|
|
636
927
|
}
|
|
637
928
|
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
929
|
+
.${rootClass} .counter-card {
|
|
930
|
+
margin: 18px auto;
|
|
931
|
+
padding: 20px 18px;
|
|
932
|
+
border-radius: 16px;
|
|
933
|
+
background: rgba(255, 255, 255, 0.06);
|
|
934
|
+
border: 1px solid rgba(255, 255, 255, 0.12);
|
|
935
|
+
backdrop-filter: blur(6px);
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
.${rootClass} .counter-card p {
|
|
939
|
+
margin: 18px 0;
|
|
940
|
+
font-size: 10px;
|
|
941
|
+
white-space: nowrap;
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
.${rootClass} .counter-card button {
|
|
945
|
+
border: 1px solid rgba(63, 185, 80, 0.45);
|
|
946
|
+
border-radius: 999px;
|
|
947
|
+
padding: 9px 24px;
|
|
948
|
+
font-size: 14px;
|
|
949
|
+
font-weight: 600;
|
|
950
|
+
color: #ffffff;
|
|
951
|
+
background: linear-gradient(135deg, #3fb950, #22c55e 55%, #16a34a);
|
|
952
|
+
box-shadow: 0 10px 20px rgba(22, 163, 74, 0.28), inset 0 1px 0 rgba(255, 255, 255, 0.25);
|
|
647
953
|
cursor: pointer;
|
|
648
|
-
transition:
|
|
954
|
+
transition: transform 0.2s ease, box-shadow 0.2s ease, filter 0.2s ease;
|
|
649
955
|
}
|
|
650
956
|
|
|
651
|
-
button:hover {
|
|
652
|
-
|
|
957
|
+
.${rootClass} .counter-card button:hover {
|
|
958
|
+
transform: translateY(-1px);
|
|
959
|
+
box-shadow: 0 14px 28px rgba(22, 163, 74, 0.32), inset 0 1px 0 rgba(255, 255, 255, 0.35);
|
|
960
|
+
filter: brightness(1.03);
|
|
653
961
|
}
|
|
654
962
|
|
|
655
|
-
button:
|
|
656
|
-
|
|
657
|
-
outline: 4px auto -webkit-focus-ring-color;
|
|
963
|
+
.${rootClass} .counter-card button:active {
|
|
964
|
+
transform: translateY(0);
|
|
658
965
|
}
|
|
659
966
|
|
|
660
|
-
.
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
margin-top: 2rem;
|
|
967
|
+
.${rootClass} .counter-card button:focus-visible {
|
|
968
|
+
outline: 3px solid rgba(63, 185, 80, 0.35);
|
|
969
|
+
outline-offset: 3px;
|
|
664
970
|
}
|
|
665
971
|
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
972
|
+
.${rootClass} .read-the-docs {
|
|
973
|
+
color: rgba(255, 255, 255, 0.58);
|
|
974
|
+
font-size: 12px;
|
|
975
|
+
text-wrap: balance;
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
.${rootClass} code {
|
|
979
|
+
background: rgba(255, 255, 255, 0.12);
|
|
980
|
+
padding: 2px 6px;
|
|
981
|
+
border-radius: 6px;
|
|
982
|
+
font-size: 11px;
|
|
983
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New',
|
|
984
|
+
monospace;
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
@keyframes logo-spin {
|
|
988
|
+
from {
|
|
989
|
+
transform: rotate(0deg);
|
|
990
|
+
}
|
|
991
|
+
to {
|
|
992
|
+
transform: rotate(360deg);
|
|
993
|
+
}
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
997
|
+
.${rootClass} .logo.react {
|
|
998
|
+
animation: logo-spin infinite 20s linear;
|
|
999
|
+
}
|
|
671
1000
|
}
|
|
672
1001
|
|
|
673
1002
|
@media (prefers-color-scheme: dark) {
|
|
674
|
-
|
|
675
|
-
|
|
1003
|
+
.${rootClass} h1 {
|
|
1004
|
+
color: #f8fafc;
|
|
676
1005
|
}
|
|
677
1006
|
|
|
678
|
-
|
|
679
|
-
|
|
1007
|
+
.${rootClass} .logo.devto {
|
|
1008
|
+
border: 1px solid rgba(63, 185, 80, 0.35);
|
|
1009
|
+
box-shadow: 0 10px 26px rgba(2, 6, 23, 0.55);
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
.${rootClass} .subtitle {
|
|
1013
|
+
color: rgba(226, 232, 240, 0.8);
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
.${rootClass} .counter-card {
|
|
1017
|
+
background: rgba(255, 255, 255, 0.08);
|
|
1018
|
+
border-color: rgba(148, 163, 184, 0.25);
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
.${rootClass} .counter-card p {
|
|
1022
|
+
color: rgba(226, 232, 240, 0.82);
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
.${rootClass} .read-the-docs {
|
|
1026
|
+
color: rgba(148, 163, 184, 0.75);
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
.${rootClass} code {
|
|
1030
|
+
background: rgba(148, 163, 184, 0.18);
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
|
|
1034
|
+
@media (prefers-color-scheme: light) {
|
|
1035
|
+
.${rootClass} .subtitle {
|
|
1036
|
+
color: #4b5563;
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
.${rootClass} .counter-card {
|
|
1040
|
+
background: #f8fafc;
|
|
1041
|
+
border-color: #e2e8f0;
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
.${rootClass} .counter-card button {
|
|
1045
|
+
color: #ffffff;
|
|
1046
|
+
box-shadow: 0 10px 18px rgba(15, 23, 42, 0.18), inset 0 1px 0 rgba(255, 255, 255, 0.3);
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
.${rootClass} .read-the-docs {
|
|
1050
|
+
color: #6b7280;
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
.${rootClass} code {
|
|
1054
|
+
background: #e2e8f0;
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
@media (max-width: 360px) {
|
|
1059
|
+
.${rootClass} {
|
|
1060
|
+
padding: 18px 10px 24px;
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
.${rootClass} .logo-row {
|
|
1064
|
+
gap: 8px;
|
|
1065
|
+
margin-bottom: 14px;
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
.${rootClass} .logo {
|
|
1069
|
+
height: 40px;
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1072
|
+
.${rootClass} h1 {
|
|
1073
|
+
font-size: 28px;
|
|
1074
|
+
}
|
|
1075
|
+
|
|
1076
|
+
.${rootClass} .subtitle {
|
|
1077
|
+
font-size: 12px;
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
.${rootClass} .counter-card {
|
|
1081
|
+
padding: 18px 16px;
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
.${rootClass} .counter-card button {
|
|
1085
|
+
padding: 8px 20px;
|
|
1086
|
+
font-size: 13px;
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
.${rootClass} .read-the-docs {
|
|
1090
|
+
font-size: 11px;
|
|
680
1091
|
}
|
|
681
1092
|
}
|
|
682
1093
|
`;
|
|
@@ -866,6 +1277,10 @@ For now, please use React or stay tuned for updates!`,
|
|
|
866
1277
|
const pkgPath = path.join(root, "package.json");
|
|
867
1278
|
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
|
|
868
1279
|
pkg.name = toValidPackageName(getProjectName());
|
|
1280
|
+
pkg.scripts = pkg.scripts ?? {};
|
|
1281
|
+
if (!pkg.scripts["build:lib"]) {
|
|
1282
|
+
pkg.scripts["build:lib"] = "dev-to build";
|
|
1283
|
+
}
|
|
869
1284
|
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
|
|
870
1285
|
const isTs = template.includes("ts");
|
|
871
1286
|
if (isReactSwc) {
|
|
@@ -887,6 +1302,9 @@ For now, please use React or stay tuned for updates!`,
|
|
|
887
1302
|
patched = updatePluginComponentName(patched, pluginName, componentName, projectName);
|
|
888
1303
|
fs.writeFileSync(viteConfigPath, patched);
|
|
889
1304
|
}
|
|
1305
|
+
spinner.message("Updating template files...");
|
|
1306
|
+
ensureDevtoLogo(root);
|
|
1307
|
+
updateAppTemplate(root, componentName, isTs);
|
|
890
1308
|
spinner.message(`Creating component ${componentName}...`);
|
|
891
1309
|
createComponentFile(root, componentName, isTs);
|
|
892
1310
|
let completionMessage = "Project created";
|