drop2run 0.4.0 → 0.5.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/README.md +2 -1
- package/dist/index.js +529 -50
- package/dist/{package-Cz51eZ2C.js → package-DXmy47q4.js} +3 -3
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# drop2run
|
|
2
2
|
|
|
3
|
-
Publish a
|
|
3
|
+
Publish a page, a folder of documents or a built site to [Drop2Run](https://dropto.run) from the
|
|
4
|
+
command line — by hand, from CI, or from a coding agent.
|
|
4
5
|
|
|
5
6
|
```bash
|
|
6
7
|
npm i -g drop2run
|
package/dist/index.js
CHANGED
|
@@ -439,6 +439,485 @@ async function problemToError(response) {
|
|
|
439
439
|
const message = typeof problem.detail === "string" ? problem.detail : typeof problem.title === "string" ? problem.title : `The server responded with ${response.status}.`;
|
|
440
440
|
return new DeployError(code, message, problem);
|
|
441
441
|
}
|
|
442
|
+
const FILE_TYPES = [
|
|
443
|
+
// Documents. The three extensions that make a folder a documents site.
|
|
444
|
+
{
|
|
445
|
+
ext: ".md",
|
|
446
|
+
mime: "text/markdown; charset=utf-8",
|
|
447
|
+
kind: "markdown",
|
|
448
|
+
document: true,
|
|
449
|
+
reader: true,
|
|
450
|
+
editable: true
|
|
451
|
+
},
|
|
452
|
+
{
|
|
453
|
+
ext: ".markdown",
|
|
454
|
+
mime: "text/markdown; charset=utf-8",
|
|
455
|
+
kind: "markdown",
|
|
456
|
+
document: true,
|
|
457
|
+
reader: true,
|
|
458
|
+
editable: true
|
|
459
|
+
},
|
|
460
|
+
{
|
|
461
|
+
ext: ".pdf",
|
|
462
|
+
mime: "application/pdf",
|
|
463
|
+
kind: "pdf",
|
|
464
|
+
document: true,
|
|
465
|
+
reader: true,
|
|
466
|
+
editable: false
|
|
467
|
+
},
|
|
468
|
+
// Office documents and ebooks. Each has its own kind because each needs its own renderer, loaded
|
|
469
|
+
// only when one is opened — `.docx` through mammoth, `.xlsx` through read-excel-file, `.epub`
|
|
470
|
+
// through foliate-js.
|
|
471
|
+
{
|
|
472
|
+
ext: ".docx",
|
|
473
|
+
mime: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
474
|
+
kind: "docx",
|
|
475
|
+
document: true,
|
|
476
|
+
reader: true,
|
|
477
|
+
editable: false
|
|
478
|
+
},
|
|
479
|
+
{
|
|
480
|
+
ext: ".xlsx",
|
|
481
|
+
mime: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
482
|
+
kind: "xlsx",
|
|
483
|
+
document: true,
|
|
484
|
+
reader: true,
|
|
485
|
+
editable: false
|
|
486
|
+
},
|
|
487
|
+
{
|
|
488
|
+
ext: ".epub",
|
|
489
|
+
mime: "application/epub+zip",
|
|
490
|
+
kind: "epub",
|
|
491
|
+
document: true,
|
|
492
|
+
reader: true,
|
|
493
|
+
editable: false
|
|
494
|
+
},
|
|
495
|
+
// Prose the reader shows preformatted.
|
|
496
|
+
{
|
|
497
|
+
ext: ".txt",
|
|
498
|
+
mime: "text/plain; charset=utf-8",
|
|
499
|
+
kind: "text",
|
|
500
|
+
document: false,
|
|
501
|
+
reader: true,
|
|
502
|
+
editable: true
|
|
503
|
+
},
|
|
504
|
+
{
|
|
505
|
+
ext: ".log",
|
|
506
|
+
mime: "text/plain; charset=utf-8",
|
|
507
|
+
kind: "text",
|
|
508
|
+
document: false,
|
|
509
|
+
reader: true,
|
|
510
|
+
editable: false
|
|
511
|
+
},
|
|
512
|
+
{
|
|
513
|
+
ext: ".csv",
|
|
514
|
+
mime: "text/csv; charset=utf-8",
|
|
515
|
+
kind: "text",
|
|
516
|
+
document: false,
|
|
517
|
+
reader: true,
|
|
518
|
+
editable: true
|
|
519
|
+
},
|
|
520
|
+
// Structured text. Read through the reader inside a folder of notes, which is why these carry
|
|
521
|
+
// `reader: true` while the source formats below do not.
|
|
522
|
+
{
|
|
523
|
+
ext: ".json",
|
|
524
|
+
mime: "application/json",
|
|
525
|
+
kind: "code",
|
|
526
|
+
document: false,
|
|
527
|
+
reader: true,
|
|
528
|
+
editable: true
|
|
529
|
+
},
|
|
530
|
+
{
|
|
531
|
+
ext: ".yaml",
|
|
532
|
+
mime: "text/yaml; charset=utf-8",
|
|
533
|
+
kind: "code",
|
|
534
|
+
document: false,
|
|
535
|
+
reader: true,
|
|
536
|
+
editable: true
|
|
537
|
+
},
|
|
538
|
+
{
|
|
539
|
+
ext: ".yml",
|
|
540
|
+
mime: "text/yaml; charset=utf-8",
|
|
541
|
+
kind: "code",
|
|
542
|
+
document: false,
|
|
543
|
+
reader: true,
|
|
544
|
+
editable: true
|
|
545
|
+
},
|
|
546
|
+
{
|
|
547
|
+
// No registered media type, so it takes text/plain rather than an invented one. The point is
|
|
548
|
+
// only that a browser shows it instead of downloading it.
|
|
549
|
+
ext: ".toml",
|
|
550
|
+
mime: "text/plain; charset=utf-8",
|
|
551
|
+
kind: "code",
|
|
552
|
+
document: false,
|
|
553
|
+
reader: true,
|
|
554
|
+
editable: true
|
|
555
|
+
},
|
|
556
|
+
// Source the viewer highlights. A link straight to one of these hands over the file.
|
|
557
|
+
{
|
|
558
|
+
ext: ".css",
|
|
559
|
+
mime: "text/css; charset=utf-8",
|
|
560
|
+
kind: "code",
|
|
561
|
+
document: false,
|
|
562
|
+
reader: false,
|
|
563
|
+
editable: true
|
|
564
|
+
},
|
|
565
|
+
{
|
|
566
|
+
ext: ".js",
|
|
567
|
+
mime: "text/javascript; charset=utf-8",
|
|
568
|
+
kind: "code",
|
|
569
|
+
document: false,
|
|
570
|
+
reader: false,
|
|
571
|
+
editable: true
|
|
572
|
+
},
|
|
573
|
+
{
|
|
574
|
+
ext: ".ts",
|
|
575
|
+
mime: null,
|
|
576
|
+
kind: "code",
|
|
577
|
+
document: false,
|
|
578
|
+
reader: false,
|
|
579
|
+
editable: false
|
|
580
|
+
},
|
|
581
|
+
{
|
|
582
|
+
ext: ".tsx",
|
|
583
|
+
mime: null,
|
|
584
|
+
kind: "code",
|
|
585
|
+
document: false,
|
|
586
|
+
reader: false,
|
|
587
|
+
editable: false
|
|
588
|
+
},
|
|
589
|
+
{
|
|
590
|
+
ext: ".jsx",
|
|
591
|
+
mime: null,
|
|
592
|
+
kind: "code",
|
|
593
|
+
document: false,
|
|
594
|
+
reader: false,
|
|
595
|
+
editable: false
|
|
596
|
+
},
|
|
597
|
+
{
|
|
598
|
+
ext: ".sh",
|
|
599
|
+
mime: null,
|
|
600
|
+
kind: "code",
|
|
601
|
+
document: false,
|
|
602
|
+
reader: false,
|
|
603
|
+
editable: false
|
|
604
|
+
},
|
|
605
|
+
// The languages an assistant writes most, beyond the web's own. Same row as `.ts`: shown as source
|
|
606
|
+
// when somebody opens one in the reader or publishes it on its own, handed over as a file when a
|
|
607
|
+
// link names it directly, and no media type — adding one changes what a browser does with a
|
|
608
|
+
// published file, which I10 makes a decision of its own rather than a side effect of this list.
|
|
609
|
+
{
|
|
610
|
+
ext: ".py",
|
|
611
|
+
mime: null,
|
|
612
|
+
kind: "code",
|
|
613
|
+
document: false,
|
|
614
|
+
reader: false,
|
|
615
|
+
editable: false
|
|
616
|
+
},
|
|
617
|
+
{
|
|
618
|
+
ext: ".sql",
|
|
619
|
+
mime: null,
|
|
620
|
+
kind: "code",
|
|
621
|
+
document: false,
|
|
622
|
+
reader: false,
|
|
623
|
+
editable: false
|
|
624
|
+
},
|
|
625
|
+
{
|
|
626
|
+
ext: ".go",
|
|
627
|
+
mime: null,
|
|
628
|
+
kind: "code",
|
|
629
|
+
document: false,
|
|
630
|
+
reader: false,
|
|
631
|
+
editable: false
|
|
632
|
+
},
|
|
633
|
+
{
|
|
634
|
+
ext: ".rs",
|
|
635
|
+
mime: null,
|
|
636
|
+
kind: "code",
|
|
637
|
+
document: false,
|
|
638
|
+
reader: false,
|
|
639
|
+
editable: false
|
|
640
|
+
},
|
|
641
|
+
{
|
|
642
|
+
ext: ".java",
|
|
643
|
+
mime: null,
|
|
644
|
+
kind: "code",
|
|
645
|
+
document: false,
|
|
646
|
+
reader: false,
|
|
647
|
+
editable: false
|
|
648
|
+
},
|
|
649
|
+
{
|
|
650
|
+
ext: ".kt",
|
|
651
|
+
mime: null,
|
|
652
|
+
kind: "code",
|
|
653
|
+
document: false,
|
|
654
|
+
reader: false,
|
|
655
|
+
editable: false
|
|
656
|
+
},
|
|
657
|
+
{
|
|
658
|
+
ext: ".swift",
|
|
659
|
+
mime: null,
|
|
660
|
+
kind: "code",
|
|
661
|
+
document: false,
|
|
662
|
+
reader: false,
|
|
663
|
+
editable: false
|
|
664
|
+
},
|
|
665
|
+
{
|
|
666
|
+
ext: ".rb",
|
|
667
|
+
mime: null,
|
|
668
|
+
kind: "code",
|
|
669
|
+
document: false,
|
|
670
|
+
reader: false,
|
|
671
|
+
editable: false
|
|
672
|
+
},
|
|
673
|
+
{
|
|
674
|
+
ext: ".php",
|
|
675
|
+
mime: null,
|
|
676
|
+
kind: "code",
|
|
677
|
+
document: false,
|
|
678
|
+
reader: false,
|
|
679
|
+
editable: false
|
|
680
|
+
},
|
|
681
|
+
{
|
|
682
|
+
ext: ".c",
|
|
683
|
+
mime: null,
|
|
684
|
+
kind: "code",
|
|
685
|
+
document: false,
|
|
686
|
+
reader: false,
|
|
687
|
+
editable: false
|
|
688
|
+
},
|
|
689
|
+
{
|
|
690
|
+
ext: ".h",
|
|
691
|
+
mime: null,
|
|
692
|
+
kind: "code",
|
|
693
|
+
document: false,
|
|
694
|
+
reader: false,
|
|
695
|
+
editable: false
|
|
696
|
+
},
|
|
697
|
+
{
|
|
698
|
+
ext: ".cpp",
|
|
699
|
+
mime: null,
|
|
700
|
+
kind: "code",
|
|
701
|
+
document: false,
|
|
702
|
+
reader: false,
|
|
703
|
+
editable: false
|
|
704
|
+
},
|
|
705
|
+
{
|
|
706
|
+
ext: ".cs",
|
|
707
|
+
mime: null,
|
|
708
|
+
kind: "code",
|
|
709
|
+
document: false,
|
|
710
|
+
reader: false,
|
|
711
|
+
editable: false
|
|
712
|
+
},
|
|
713
|
+
{
|
|
714
|
+
ext: ".r",
|
|
715
|
+
mime: null,
|
|
716
|
+
kind: "code",
|
|
717
|
+
document: false,
|
|
718
|
+
reader: false,
|
|
719
|
+
editable: false
|
|
720
|
+
},
|
|
721
|
+
{
|
|
722
|
+
ext: ".xml",
|
|
723
|
+
mime: "application/xml",
|
|
724
|
+
kind: "code",
|
|
725
|
+
document: false,
|
|
726
|
+
reader: false,
|
|
727
|
+
editable: true
|
|
728
|
+
},
|
|
729
|
+
// Pictures, shown with an img element.
|
|
730
|
+
{
|
|
731
|
+
ext: ".png",
|
|
732
|
+
mime: "image/png",
|
|
733
|
+
kind: "image",
|
|
734
|
+
document: false,
|
|
735
|
+
reader: false,
|
|
736
|
+
editable: false
|
|
737
|
+
},
|
|
738
|
+
{
|
|
739
|
+
ext: ".jpg",
|
|
740
|
+
mime: "image/jpeg",
|
|
741
|
+
kind: "image",
|
|
742
|
+
document: false,
|
|
743
|
+
reader: false,
|
|
744
|
+
editable: false
|
|
745
|
+
},
|
|
746
|
+
{
|
|
747
|
+
ext: ".jpeg",
|
|
748
|
+
mime: "image/jpeg",
|
|
749
|
+
kind: "image",
|
|
750
|
+
document: false,
|
|
751
|
+
reader: false,
|
|
752
|
+
editable: false
|
|
753
|
+
},
|
|
754
|
+
{
|
|
755
|
+
ext: ".gif",
|
|
756
|
+
mime: "image/gif",
|
|
757
|
+
kind: "image",
|
|
758
|
+
document: false,
|
|
759
|
+
reader: false,
|
|
760
|
+
editable: false
|
|
761
|
+
},
|
|
762
|
+
{
|
|
763
|
+
ext: ".webp",
|
|
764
|
+
mime: "image/webp",
|
|
765
|
+
kind: "image",
|
|
766
|
+
document: false,
|
|
767
|
+
reader: false,
|
|
768
|
+
editable: false
|
|
769
|
+
},
|
|
770
|
+
{
|
|
771
|
+
ext: ".avif",
|
|
772
|
+
mime: "image/avif",
|
|
773
|
+
kind: "image",
|
|
774
|
+
document: false,
|
|
775
|
+
reader: false,
|
|
776
|
+
editable: false
|
|
777
|
+
},
|
|
778
|
+
{
|
|
779
|
+
// Text, hand-edited in practice, and script-carrying. Editable anyway: the Worker derives the
|
|
780
|
+
// type at serve time (I10) and already serves whatever was uploaded, so withholding the edit
|
|
781
|
+
// would withhold nothing else.
|
|
782
|
+
ext: ".svg",
|
|
783
|
+
mime: "image/svg+xml",
|
|
784
|
+
kind: "image",
|
|
785
|
+
document: false,
|
|
786
|
+
reader: false,
|
|
787
|
+
editable: true
|
|
788
|
+
},
|
|
789
|
+
{
|
|
790
|
+
ext: ".ico",
|
|
791
|
+
mime: "image/x-icon",
|
|
792
|
+
kind: "image",
|
|
793
|
+
document: false,
|
|
794
|
+
reader: false,
|
|
795
|
+
editable: false
|
|
796
|
+
},
|
|
797
|
+
// A customer's own pages. Never rendered inside the reader.
|
|
798
|
+
{
|
|
799
|
+
ext: ".html",
|
|
800
|
+
mime: "text/html; charset=utf-8",
|
|
801
|
+
kind: "html",
|
|
802
|
+
document: false,
|
|
803
|
+
reader: false,
|
|
804
|
+
editable: true
|
|
805
|
+
},
|
|
806
|
+
{
|
|
807
|
+
// ⚠️ No media type, and that is the state of the code rather than a decision: `TYPES` in
|
|
808
|
+
// `headers.ts` has never held `htm`, so a published `.htm` is served as octet-stream and
|
|
809
|
+
// downloads instead of rendering. Recorded here rather than fixed, because this table was
|
|
810
|
+
// introduced as a refactor and a refactor that changes what a URL answers is not one.
|
|
811
|
+
ext: ".htm",
|
|
812
|
+
mime: null,
|
|
813
|
+
kind: "html",
|
|
814
|
+
document: false,
|
|
815
|
+
reader: false,
|
|
816
|
+
editable: true
|
|
817
|
+
},
|
|
818
|
+
// Everything below renders as nothing — the viewer offers a download — but still needs a media
|
|
819
|
+
// type, because these are the files a static site is built out of.
|
|
820
|
+
{
|
|
821
|
+
ext: ".mjs",
|
|
822
|
+
mime: "text/javascript; charset=utf-8",
|
|
823
|
+
kind: "binary",
|
|
824
|
+
document: false,
|
|
825
|
+
reader: false,
|
|
826
|
+
editable: true
|
|
827
|
+
},
|
|
828
|
+
{
|
|
829
|
+
ext: ".cjs",
|
|
830
|
+
mime: null,
|
|
831
|
+
kind: "binary",
|
|
832
|
+
document: false,
|
|
833
|
+
reader: false,
|
|
834
|
+
editable: true
|
|
835
|
+
},
|
|
836
|
+
{
|
|
837
|
+
ext: ".map",
|
|
838
|
+
mime: "application/json",
|
|
839
|
+
kind: "binary",
|
|
840
|
+
document: false,
|
|
841
|
+
reader: false,
|
|
842
|
+
editable: false
|
|
843
|
+
},
|
|
844
|
+
{
|
|
845
|
+
ext: ".wasm",
|
|
846
|
+
mime: "application/wasm",
|
|
847
|
+
kind: "binary",
|
|
848
|
+
document: false,
|
|
849
|
+
reader: false,
|
|
850
|
+
editable: false
|
|
851
|
+
},
|
|
852
|
+
{
|
|
853
|
+
ext: ".woff2",
|
|
854
|
+
mime: "font/woff2",
|
|
855
|
+
kind: "binary",
|
|
856
|
+
document: false,
|
|
857
|
+
reader: false,
|
|
858
|
+
editable: false
|
|
859
|
+
},
|
|
860
|
+
{
|
|
861
|
+
ext: ".woff",
|
|
862
|
+
mime: "font/woff",
|
|
863
|
+
kind: "binary",
|
|
864
|
+
document: false,
|
|
865
|
+
reader: false,
|
|
866
|
+
editable: false
|
|
867
|
+
},
|
|
868
|
+
{
|
|
869
|
+
ext: ".ttf",
|
|
870
|
+
mime: "font/ttf",
|
|
871
|
+
kind: "binary",
|
|
872
|
+
document: false,
|
|
873
|
+
reader: false,
|
|
874
|
+
editable: false
|
|
875
|
+
},
|
|
876
|
+
{
|
|
877
|
+
ext: ".mp4",
|
|
878
|
+
mime: "video/mp4",
|
|
879
|
+
kind: "binary",
|
|
880
|
+
document: false,
|
|
881
|
+
reader: false,
|
|
882
|
+
editable: false
|
|
883
|
+
},
|
|
884
|
+
{
|
|
885
|
+
ext: ".webm",
|
|
886
|
+
mime: "video/webm",
|
|
887
|
+
kind: "binary",
|
|
888
|
+
document: false,
|
|
889
|
+
reader: false,
|
|
890
|
+
editable: false
|
|
891
|
+
}
|
|
892
|
+
];
|
|
893
|
+
function extensionsWhere(include) {
|
|
894
|
+
return FILE_TYPES.filter(include).map((type) => type.ext);
|
|
895
|
+
}
|
|
896
|
+
const DOCUMENT_EXTENSIONS$1 = extensionsWhere((type) => type.document);
|
|
897
|
+
const VIEWABLE_EXTENSIONS$1 = extensionsWhere(
|
|
898
|
+
(type) => type.kind !== "binary"
|
|
899
|
+
);
|
|
900
|
+
extensionsWhere((type) => type.reader);
|
|
901
|
+
extensionsWhere((type) => type.editable);
|
|
902
|
+
const WEB_ASSET_EXTENSIONS = [
|
|
903
|
+
".html",
|
|
904
|
+
".htm",
|
|
905
|
+
".js",
|
|
906
|
+
".mjs",
|
|
907
|
+
".cjs",
|
|
908
|
+
".css"
|
|
909
|
+
];
|
|
910
|
+
const GALLERY_EXTENSIONS = extensionsWhere(
|
|
911
|
+
(type) => type.kind === "image"
|
|
912
|
+
);
|
|
913
|
+
Object.fromEntries(
|
|
914
|
+
FILE_TYPES.filter((type) => type.mime !== null).map((type) => [type.ext, type.mime])
|
|
915
|
+
);
|
|
916
|
+
function extensionOf(path) {
|
|
917
|
+
const name = path.slice(path.lastIndexOf("/") + 1);
|
|
918
|
+
const dot = name.lastIndexOf(".");
|
|
919
|
+
return dot <= 0 ? "" : name.slice(dot).toLowerCase();
|
|
920
|
+
}
|
|
442
921
|
async function sha256Hex(bytes) {
|
|
443
922
|
const digest = await crypto.subtle.digest("SHA-256", bytes.slice().buffer);
|
|
444
923
|
return [...new Uint8Array(digest)].map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
@@ -470,52 +949,29 @@ function shouldIgnore(path) {
|
|
|
470
949
|
return segments.some((segment) => IGNORED_DIRECTORIES.includes(segment));
|
|
471
950
|
}
|
|
472
951
|
const REQUIRED_INDEX = "index.html";
|
|
473
|
-
const DOCUMENT_EXTENSIONS =
|
|
952
|
+
const DOCUMENT_EXTENSIONS = DOCUMENT_EXTENSIONS$1;
|
|
474
953
|
function isDocumentPath(path) {
|
|
475
954
|
const lower = path.toLowerCase();
|
|
476
955
|
return DOCUMENT_EXTENSIONS.some((extension) => lower.endsWith(extension));
|
|
477
956
|
}
|
|
478
|
-
const VIEWABLE_EXTENSIONS =
|
|
479
|
-
// Documents — these also count at any depth, via DOCUMENT_EXTENSIONS.
|
|
480
|
-
".md",
|
|
481
|
-
".markdown",
|
|
482
|
-
".pdf",
|
|
483
|
-
// Prose the reader shows preformatted.
|
|
484
|
-
".txt",
|
|
485
|
-
".log",
|
|
486
|
-
".csv",
|
|
487
|
-
// Source the reader shows with highlighting.
|
|
488
|
-
".json",
|
|
489
|
-
".yaml",
|
|
490
|
-
".yml",
|
|
491
|
-
".toml",
|
|
492
|
-
".css",
|
|
493
|
-
".js",
|
|
494
|
-
".ts",
|
|
495
|
-
".tsx",
|
|
496
|
-
".jsx",
|
|
497
|
-
".sh",
|
|
498
|
-
".xml",
|
|
499
|
-
// Pictures the reader shows with an img element.
|
|
500
|
-
".png",
|
|
501
|
-
".jpg",
|
|
502
|
-
".jpeg",
|
|
503
|
-
".gif",
|
|
504
|
-
".webp",
|
|
505
|
-
".avif",
|
|
506
|
-
".svg",
|
|
507
|
-
".ico",
|
|
508
|
-
// See the note above: a floor for a caller that did not rename it.
|
|
509
|
-
".html",
|
|
510
|
-
".htm"
|
|
511
|
-
];
|
|
957
|
+
const VIEWABLE_EXTENSIONS = VIEWABLE_EXTENSIONS$1;
|
|
512
958
|
function isViewablePath(path) {
|
|
513
959
|
const lower = path.toLowerCase();
|
|
514
960
|
return VIEWABLE_EXTENSIONS.some((extension) => lower.endsWith(extension));
|
|
515
961
|
}
|
|
962
|
+
function isImageFolder(paths) {
|
|
963
|
+
let pictures = false;
|
|
964
|
+
for (const path of paths) {
|
|
965
|
+
const ext = extensionOf(path);
|
|
966
|
+
if (WEB_ASSET_EXTENSIONS.includes(ext)) return false;
|
|
967
|
+
if (GALLERY_EXTENSIONS.includes(ext)) pictures = true;
|
|
968
|
+
}
|
|
969
|
+
return pictures;
|
|
970
|
+
}
|
|
516
971
|
function canPublish(paths) {
|
|
517
972
|
if (paths.some((path) => path === REQUIRED_INDEX)) return true;
|
|
518
973
|
if (paths.some(isDocumentPath)) return true;
|
|
974
|
+
if (isImageFolder(paths)) return true;
|
|
519
975
|
return paths.length === 1 && paths[0] !== void 0 && isViewablePath(paths[0]);
|
|
520
976
|
}
|
|
521
977
|
function renameOfLoneHtmlPage(paths) {
|
|
@@ -544,37 +1000,42 @@ function checkLimits(files, limits) {
|
|
|
544
1000
|
`A site needs an ${REQUIRED_INDEX} at its top level, or at least one .md or .pdf file to publish as a documents site — or be a single file that can be displayed on its own, such as a note, a PDF, a page or an image. Drop the folder that contains it, not the folder above.`
|
|
545
1001
|
);
|
|
546
1002
|
}
|
|
547
|
-
|
|
1003
|
+
const refusal = sizeRefusal(
|
|
1004
|
+
files.map((file) => ({ path: file.path, size: file.bytes.length })),
|
|
1005
|
+
limits
|
|
1006
|
+
);
|
|
1007
|
+
if (refusal) throw refusal;
|
|
1008
|
+
}
|
|
1009
|
+
function sizeRefusal(files, limits) {
|
|
1010
|
+
if (!limits) return null;
|
|
548
1011
|
if (files.length > limits.maxFiles) {
|
|
549
|
-
|
|
1012
|
+
return new DeployError(
|
|
550
1013
|
ClientErrorCode.TooManyFiles,
|
|
551
1014
|
`That is ${files.length} files, and this plan allows ${limits.maxFiles}.`,
|
|
552
1015
|
{ limit: limits.maxFiles, actual: files.length }
|
|
553
1016
|
);
|
|
554
1017
|
}
|
|
555
|
-
const oversized = files.find((file) => file.
|
|
1018
|
+
const oversized = files.find((file) => file.size > limits.maxFileBytes);
|
|
556
1019
|
if (oversized) {
|
|
557
|
-
|
|
1020
|
+
return new DeployError(
|
|
558
1021
|
ClientErrorCode.FileTooLarge,
|
|
559
|
-
`${oversized.path} is ${formatBytes$1(oversized.
|
|
1022
|
+
`${oversized.path} is ${formatBytes$1(oversized.size)}, and this plan allows ${formatBytes$1(limits.maxFileBytes)} per file.`,
|
|
560
1023
|
{
|
|
561
1024
|
path: oversized.path,
|
|
562
1025
|
limit: limits.maxFileBytes,
|
|
563
|
-
actual: oversized.
|
|
1026
|
+
actual: oversized.size
|
|
564
1027
|
}
|
|
565
1028
|
);
|
|
566
1029
|
}
|
|
567
|
-
const total =
|
|
1030
|
+
const total = files.reduce((sum, file) => sum + file.size, 0);
|
|
568
1031
|
if (limits.maxSiteBytes !== null && total > limits.maxSiteBytes) {
|
|
569
|
-
|
|
1032
|
+
return new DeployError(
|
|
570
1033
|
ClientErrorCode.TooLarge,
|
|
571
1034
|
`That drop is ${formatBytes$1(total)}, and this plan allows ${formatBytes$1(limits.maxSiteBytes)}.`,
|
|
572
1035
|
{ limit: limits.maxSiteBytes, actual: total }
|
|
573
1036
|
);
|
|
574
1037
|
}
|
|
575
|
-
|
|
576
|
-
function totalBytes(files) {
|
|
577
|
-
return files.reduce((sum, file) => sum + file.bytes.length, 0);
|
|
1038
|
+
return null;
|
|
578
1039
|
}
|
|
579
1040
|
const MAX_NAME_LENGTH = 60;
|
|
580
1041
|
const HEAD_BYTES = 64 * 1024;
|
|
@@ -926,8 +1387,11 @@ async function publish(credentials, source, site, onProgress, subdomain) {
|
|
|
926
1387
|
});
|
|
927
1388
|
return { url, siteId: target.siteId, subdomain: target.subdomain, files, unchanged };
|
|
928
1389
|
}
|
|
929
|
-
function publishDirectory(credentials, directory, site, onProgress, subdomain) {
|
|
930
|
-
|
|
1390
|
+
async function publishDirectory(credentials, directory, site, onProgress, subdomain) {
|
|
1391
|
+
const found = await stat(directory).catch(() => null);
|
|
1392
|
+
if (found === null) throw new Error(`There is no folder at ${directory}.`);
|
|
1393
|
+
if (!found.isDirectory()) throw new Error(`${directory} is a file, not a folder to publish.`);
|
|
1394
|
+
return await publish(credentials, directorySource(directory), site, onProgress, subdomain);
|
|
931
1395
|
}
|
|
932
1396
|
const silentProgress = Object.assign(() => {
|
|
933
1397
|
}, { done: () => {
|
|
@@ -1352,6 +1816,21 @@ function flagValue(args, flag) {
|
|
|
1352
1816
|
const value = args[at + 1];
|
|
1353
1817
|
return value === void 0 || value.startsWith("-") ? void 0 : value;
|
|
1354
1818
|
}
|
|
1819
|
+
const VALUE_FLAGS = ["--site", "--subdomain"];
|
|
1820
|
+
function positionals(argv) {
|
|
1821
|
+
const found = [];
|
|
1822
|
+
for (let at = 0; at < argv.length; at++) {
|
|
1823
|
+
const argument = argv[at];
|
|
1824
|
+
if (argument === void 0) continue;
|
|
1825
|
+
if (VALUE_FLAGS.includes(argument)) {
|
|
1826
|
+
const value = argv[at + 1];
|
|
1827
|
+
if (value !== void 0 && !value.startsWith("-")) at++;
|
|
1828
|
+
continue;
|
|
1829
|
+
}
|
|
1830
|
+
if (!argument.startsWith("-")) found.push(argument);
|
|
1831
|
+
}
|
|
1832
|
+
return found;
|
|
1833
|
+
}
|
|
1355
1834
|
function subdomainFlagProblem(argv, command, site, subdomain) {
|
|
1356
1835
|
if (!argv.includes("--subdomain")) return void 0;
|
|
1357
1836
|
if (subdomain === void 0) {
|
|
@@ -1367,10 +1846,10 @@ function subdomainFlagProblem(argv, command, site, subdomain) {
|
|
|
1367
1846
|
}
|
|
1368
1847
|
async function run(argv) {
|
|
1369
1848
|
const json = argv.includes("--json");
|
|
1370
|
-
const positional = argv
|
|
1849
|
+
const positional = positionals(argv);
|
|
1371
1850
|
const [command, ...rest] = positional;
|
|
1372
1851
|
if (argv.includes("--version")) {
|
|
1373
|
-
const { version } = await import("./package-
|
|
1852
|
+
const { version } = await import("./package-DXmy47q4.js").then(
|
|
1374
1853
|
(module) => module.default
|
|
1375
1854
|
);
|
|
1376
1855
|
return { text: version, json: { version }, code: 0 };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const name = "drop2run";
|
|
2
|
-
const version = "0.
|
|
3
|
-
const description = "Publish a
|
|
2
|
+
const version = "0.5.0";
|
|
3
|
+
const description = "Publish a page, a folder of documents or a built site to Drop2Run from the command line.";
|
|
4
4
|
const license = "MIT";
|
|
5
5
|
const type = "module";
|
|
6
6
|
const bin = { "drop2run": "bin/drop2run.mjs" };
|
|
@@ -10,7 +10,7 @@ const publishConfig = { "access": "public" };
|
|
|
10
10
|
const homepage = "https://dropto.run";
|
|
11
11
|
const repository = { "type": "git", "url": "git+https://github.com/Drop-to-run/drop2run-cli.git" };
|
|
12
12
|
const bugs = { "url": "https://github.com/Drop-to-run/drop2run-cli/issues" };
|
|
13
|
-
const keywords = ["static-site", "deploy", "hosting", "cli", "ai", "claude", "agent", "llm"];
|
|
13
|
+
const keywords = ["static-site", "markdown", "pdf", "deploy", "hosting", "cli", "ai", "claude", "agent", "llm"];
|
|
14
14
|
const scripts = { "prepublishOnly": "npm run build && npm test", "build": "vite build", "typecheck": "tsc --noEmit", "test": "vitest run", "lint": "biome check .", "format": "biome check --write ." };
|
|
15
15
|
const devDependencies = { "@biomejs/biome": "^2.5.11", "@types/node": "^26.4.0", "typescript": "^5.9.3", "vite": "^7.2.1", "vitest": "^4.1.11" };
|
|
16
16
|
const _package = {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "drop2run",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Publish a
|
|
3
|
+
"version": "0.5.0",
|
|
4
|
+
"description": "Publish a page, a folder of documents or a built site to Drop2Run from the command line.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
@@ -27,6 +27,8 @@
|
|
|
27
27
|
},
|
|
28
28
|
"keywords": [
|
|
29
29
|
"static-site",
|
|
30
|
+
"markdown",
|
|
31
|
+
"pdf",
|
|
30
32
|
"deploy",
|
|
31
33
|
"hosting",
|
|
32
34
|
"cli",
|