@terrymooreii/sia 2.1.0 ā 2.1.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/_config.yml +1 -0
- package/defaults/layouts/post.njk +4 -1
- package/defaults/pages/blog.njk +1 -0
- package/defaults/pages/index.njk +1 -0
- package/defaults/pages/tag.njk +1 -0
- package/defaults/styles/main.css +303 -4
- package/defaults/styles/minimal.css +301 -4
- package/lib/build.js +9 -0
- package/lib/config.js +2 -1
- package/lib/content.js +138 -2
- package/lib/server.js +3 -3
- package/package.json +1 -1
- package/readme.md +60 -1
package/_config.yml
CHANGED
|
@@ -3,7 +3,10 @@
|
|
|
3
3
|
{% block content %}
|
|
4
4
|
<article class="post">
|
|
5
5
|
<header class="post-header">
|
|
6
|
-
<h1 class="post-title">
|
|
6
|
+
<h1 class="post-title">
|
|
7
|
+
{{ page.title }}
|
|
8
|
+
{% if page.draft %}<span class="draft-badge">Draft</span>{% endif %}
|
|
9
|
+
</h1>
|
|
7
10
|
|
|
8
11
|
<div class="post-meta">
|
|
9
12
|
<time datetime="{{ page.date | date('iso') }}">{{ page.date | date('long') }}</time>
|
package/defaults/pages/blog.njk
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
<article class="post-card">
|
|
12
12
|
<h2 class="post-card-title">
|
|
13
13
|
<a href="{{ post.url }}">{{ post.title }}</a>
|
|
14
|
+
{% if post.draft %}<span class="draft-badge">Draft</span>{% endif %}
|
|
14
15
|
</h2>
|
|
15
16
|
<div class="post-card-meta">
|
|
16
17
|
<time datetime="{{ post.date | date('iso') }}">{{ post.date | date('long') }}</time>
|
package/defaults/pages/index.njk
CHANGED
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
<article class="post-card">
|
|
18
18
|
<h3 class="post-card-title">
|
|
19
19
|
<a href="{{ post.url }}">{{ post.title }}</a>
|
|
20
|
+
{% if post.draft %}<span class="draft-badge">Draft</span>{% endif %}
|
|
20
21
|
</h3>
|
|
21
22
|
<div class="post-card-meta">
|
|
22
23
|
<time datetime="{{ post.date | date('iso') }}">{{ post.date | date('short') }}</time>
|
package/defaults/pages/tag.njk
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
<article class="post-card">
|
|
12
12
|
<h2 class="post-card-title">
|
|
13
13
|
<a href="{{ post.url }}">{{ post.title or post.excerpt }}</a>
|
|
14
|
+
{% if post.draft %}<span class="draft-badge">Draft</span>{% endif %}
|
|
14
15
|
</h2>
|
|
15
16
|
<div class="post-card-meta">
|
|
16
17
|
<time datetime="{{ post.date | date('iso') }}">{{ post.date | date('long') }}</time>
|
package/defaults/styles/main.css
CHANGED
|
@@ -341,6 +341,10 @@ img {
|
|
|
341
341
|
font-weight: 600;
|
|
342
342
|
margin: 0 0 var(--spacing-sm);
|
|
343
343
|
line-height: 1.3;
|
|
344
|
+
display: flex;
|
|
345
|
+
align-items: center;
|
|
346
|
+
flex-wrap: wrap;
|
|
347
|
+
gap: var(--spacing-sm);
|
|
344
348
|
}
|
|
345
349
|
|
|
346
350
|
.post-card-title a {
|
|
@@ -396,6 +400,10 @@ img {
|
|
|
396
400
|
letter-spacing: -0.02em;
|
|
397
401
|
margin: 0 0 var(--spacing-md);
|
|
398
402
|
line-height: 1.2;
|
|
403
|
+
display: flex;
|
|
404
|
+
align-items: center;
|
|
405
|
+
flex-wrap: wrap;
|
|
406
|
+
gap: var(--spacing-sm);
|
|
399
407
|
}
|
|
400
408
|
|
|
401
409
|
.post-meta {
|
|
@@ -566,12 +574,29 @@ img {
|
|
|
566
574
|
font-size: 0.9375rem;
|
|
567
575
|
}
|
|
568
576
|
|
|
569
|
-
|
|
570
|
-
|
|
577
|
+
/* ===== Draft Badge ===== */
|
|
578
|
+
.draft-badge {
|
|
579
|
+
display: inline-flex;
|
|
580
|
+
align-items: center;
|
|
581
|
+
padding: 0.125em 0.4em;
|
|
582
|
+
background: #f59e0b;
|
|
583
|
+
color: white;
|
|
584
|
+
font-size: 0.65rem;
|
|
585
|
+
font-weight: 600;
|
|
586
|
+
text-transform: uppercase;
|
|
587
|
+
letter-spacing: 0.05em;
|
|
588
|
+
border-radius: var(--radius-sm);
|
|
589
|
+
line-height: 1;
|
|
590
|
+
flex-shrink: 0;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
[data-theme="dark"] .draft-badge {
|
|
594
|
+
background: #fbbf24;
|
|
595
|
+
color: #1a202c;
|
|
571
596
|
}
|
|
572
597
|
|
|
573
|
-
.
|
|
574
|
-
|
|
598
|
+
.prose .draft-badge {
|
|
599
|
+
font-size: 0.6rem;
|
|
575
600
|
}
|
|
576
601
|
|
|
577
602
|
.tag-section {
|
|
@@ -793,6 +818,46 @@ img {
|
|
|
793
818
|
box-shadow: var(--shadow-md);
|
|
794
819
|
}
|
|
795
820
|
|
|
821
|
+
/* YouTube Embed Styles */
|
|
822
|
+
.prose .youtube-embed {
|
|
823
|
+
position: relative;
|
|
824
|
+
padding-bottom: 56.25%; /* 16:9 aspect ratio */
|
|
825
|
+
height: 0;
|
|
826
|
+
overflow: hidden;
|
|
827
|
+
margin: 1.5em 0;
|
|
828
|
+
border-radius: var(--radius-md);
|
|
829
|
+
box-shadow: var(--shadow-md);
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
.prose .youtube-embed iframe {
|
|
833
|
+
position: absolute;
|
|
834
|
+
top: 0;
|
|
835
|
+
left: 0;
|
|
836
|
+
width: 100%;
|
|
837
|
+
height: 100%;
|
|
838
|
+
border: 0;
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
/* Giphy Embed Styles */
|
|
842
|
+
.prose .giphy-embed {
|
|
843
|
+
position: relative;
|
|
844
|
+
padding-bottom: 100%; /* Giphy embeds are typically square */
|
|
845
|
+
height: 0;
|
|
846
|
+
overflow: hidden;
|
|
847
|
+
margin: 1.5em 0;
|
|
848
|
+
border-radius: var(--radius-md);
|
|
849
|
+
box-shadow: var(--shadow-md);
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
.prose .giphy-embed iframe {
|
|
853
|
+
position: absolute;
|
|
854
|
+
top: 0;
|
|
855
|
+
left: 0;
|
|
856
|
+
width: 100%;
|
|
857
|
+
height: 100%;
|
|
858
|
+
border: 0;
|
|
859
|
+
}
|
|
860
|
+
|
|
796
861
|
.prose a {
|
|
797
862
|
text-decoration: underline;
|
|
798
863
|
text-decoration-color: var(--color-border);
|
|
@@ -828,6 +893,240 @@ img {
|
|
|
828
893
|
font-weight: 600;
|
|
829
894
|
}
|
|
830
895
|
|
|
896
|
+
/* ===== Alert Boxes ===== */
|
|
897
|
+
.prose .markdown-alert {
|
|
898
|
+
margin: 1.5em 0;
|
|
899
|
+
padding: var(--spacing-md) var(--spacing-lg);
|
|
900
|
+
border-left: 4px solid;
|
|
901
|
+
border-radius: var(--radius-md);
|
|
902
|
+
background: var(--color-bg-alt);
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
.prose .markdown-alert-title {
|
|
906
|
+
display: flex;
|
|
907
|
+
align-items: center;
|
|
908
|
+
gap: var(--spacing-sm);
|
|
909
|
+
margin: 0 0 var(--spacing-sm) 0;
|
|
910
|
+
font-weight: 600;
|
|
911
|
+
font-style: normal;
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
.prose .markdown-alert-title svg {
|
|
915
|
+
flex-shrink: 0;
|
|
916
|
+
width: 16px;
|
|
917
|
+
height: 16px;
|
|
918
|
+
fill: currentColor;
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
/* Make SVG icons lighter in dark mode */
|
|
922
|
+
[data-theme="dark"] .prose .markdown-alert-title svg {
|
|
923
|
+
fill: currentColor;
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
.prose .markdown-alert p:last-child {
|
|
927
|
+
margin-bottom: 0;
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
/* Note Alert */
|
|
931
|
+
.prose .markdown-alert-note {
|
|
932
|
+
border-left-color: #0969da;
|
|
933
|
+
background: rgba(9, 105, 218, 0.1);
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
.prose .markdown-alert-note .markdown-alert-title {
|
|
937
|
+
color: #0969da;
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
[data-theme="dark"] .prose .markdown-alert-note {
|
|
941
|
+
background: rgba(9, 105, 218, 0.15);
|
|
942
|
+
border-left-color: #58a6ff;
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
[data-theme="dark"] .prose .markdown-alert-note .markdown-alert-title {
|
|
946
|
+
color: #58a6ff;
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
[data-theme="dark"] .prose .markdown-alert-note .markdown-alert-title svg {
|
|
950
|
+
fill: #58a6ff;
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
/* Tip Alert */
|
|
954
|
+
.prose .markdown-alert-tip {
|
|
955
|
+
border-left-color: #1a7f37;
|
|
956
|
+
background: rgba(26, 127, 55, 0.1);
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
.prose .markdown-alert-tip .markdown-alert-title {
|
|
960
|
+
color: #1a7f37;
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
[data-theme="dark"] .prose .markdown-alert-tip {
|
|
964
|
+
background: rgba(26, 127, 55, 0.15);
|
|
965
|
+
border-left-color: #3fb950;
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
[data-theme="dark"] .prose .markdown-alert-tip .markdown-alert-title {
|
|
969
|
+
color: #3fb950;
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
[data-theme="dark"] .prose .markdown-alert-tip .markdown-alert-title svg {
|
|
973
|
+
fill: #3fb950;
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
/* Important Alert */
|
|
977
|
+
.prose .markdown-alert-important {
|
|
978
|
+
border-left-color: #8250df;
|
|
979
|
+
background: rgba(130, 80, 223, 0.1);
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
.prose .markdown-alert-important .markdown-alert-title {
|
|
983
|
+
color: #8250df;
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
[data-theme="dark"] .prose .markdown-alert-important {
|
|
987
|
+
background: rgba(130, 80, 223, 0.15);
|
|
988
|
+
border-left-color: #a371f7;
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
[data-theme="dark"] .prose .markdown-alert-important .markdown-alert-title {
|
|
992
|
+
color: #a371f7;
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
[data-theme="dark"] .prose .markdown-alert-important .markdown-alert-title svg {
|
|
996
|
+
fill: #a371f7;
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
/* Warning Alert */
|
|
1000
|
+
.prose .markdown-alert-warning {
|
|
1001
|
+
border-left-color: #9a6700;
|
|
1002
|
+
background: rgba(154, 103, 0, 0.1);
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
.prose .markdown-alert-warning .markdown-alert-title {
|
|
1006
|
+
color: #9a6700;
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
[data-theme="dark"] .prose .markdown-alert-warning {
|
|
1010
|
+
background: rgba(154, 103, 0, 0.15);
|
|
1011
|
+
border-left-color: #d29922;
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
[data-theme="dark"] .prose .markdown-alert-warning .markdown-alert-title {
|
|
1015
|
+
color: #d29922;
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
[data-theme="dark"] .prose .markdown-alert-warning .markdown-alert-title svg {
|
|
1019
|
+
fill: #d29922;
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
/* Caution Alert */
|
|
1023
|
+
.prose .markdown-alert-caution {
|
|
1024
|
+
border-left-color: #cf222e;
|
|
1025
|
+
background: rgba(207, 34, 46, 0.1);
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
.prose .markdown-alert-caution .markdown-alert-title {
|
|
1029
|
+
color: #cf222e;
|
|
1030
|
+
}
|
|
1031
|
+
|
|
1032
|
+
[data-theme="dark"] .prose .markdown-alert-caution {
|
|
1033
|
+
background: rgba(207, 34, 46, 0.15);
|
|
1034
|
+
border-left-color: #f85149;
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
[data-theme="dark"] .prose .markdown-alert-caution .markdown-alert-title {
|
|
1038
|
+
color: #f85149;
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
[data-theme="dark"] .prose .markdown-alert-caution .markdown-alert-title svg {
|
|
1042
|
+
fill: #f85149;
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
/* ===== Task Lists (Checkboxes) ===== */
|
|
1046
|
+
.prose ul.contains-task-list,
|
|
1047
|
+
.prose ol.contains-task-list {
|
|
1048
|
+
list-style: none;
|
|
1049
|
+
padding-left: 0;
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
.prose .task-list-item {
|
|
1053
|
+
display: flex;
|
|
1054
|
+
align-items: flex-start;
|
|
1055
|
+
gap: var(--spacing-sm);
|
|
1056
|
+
margin-bottom: 0.5em;
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
.prose .task-list-item input[type="checkbox"] {
|
|
1060
|
+
margin-top: 0.25em;
|
|
1061
|
+
cursor: pointer;
|
|
1062
|
+
width: 1em;
|
|
1063
|
+
height: 1em;
|
|
1064
|
+
flex-shrink: 0;
|
|
1065
|
+
accent-color: var(--color-primary);
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
.prose .task-list-item input[type="checkbox"]:checked {
|
|
1069
|
+
accent-color: var(--color-primary);
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1072
|
+
/* ===== Strikethrough ===== */
|
|
1073
|
+
.prose del,
|
|
1074
|
+
.prose s {
|
|
1075
|
+
text-decoration: line-through;
|
|
1076
|
+
text-decoration-color: var(--color-text-muted);
|
|
1077
|
+
opacity: 0.7;
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
/* ===== Footnotes ===== */
|
|
1081
|
+
.prose section[data-footnotes],
|
|
1082
|
+
.prose .footnotes {
|
|
1083
|
+
margin-top: 2em;
|
|
1084
|
+
padding-top: var(--spacing-lg);
|
|
1085
|
+
border-top: 1px solid var(--color-border);
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
.prose section[data-footnotes] h2,
|
|
1089
|
+
.prose .footnotes h2 {
|
|
1090
|
+
font-size: 1rem;
|
|
1091
|
+
font-weight: 600;
|
|
1092
|
+
margin-bottom: var(--spacing-md);
|
|
1093
|
+
color: var(--color-text-muted);
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
.prose section[data-footnotes] ol,
|
|
1097
|
+
.prose .footnotes ol {
|
|
1098
|
+
padding-left: 1.5em;
|
|
1099
|
+
font-size: 0.9375rem;
|
|
1100
|
+
color: var(--color-text-muted);
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1103
|
+
.prose section[data-footnotes] li,
|
|
1104
|
+
.prose .footnotes li {
|
|
1105
|
+
margin-bottom: var(--spacing-sm);
|
|
1106
|
+
}
|
|
1107
|
+
|
|
1108
|
+
.prose .footnote-ref {
|
|
1109
|
+
font-size: 0.875em;
|
|
1110
|
+
vertical-align: super;
|
|
1111
|
+
text-decoration: none;
|
|
1112
|
+
color: var(--color-primary);
|
|
1113
|
+
margin-left: 0.2em;
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
.prose .footnote-ref:hover {
|
|
1117
|
+
text-decoration: underline;
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
.prose .footnote-backref {
|
|
1121
|
+
text-decoration: none;
|
|
1122
|
+
color: var(--color-primary);
|
|
1123
|
+
margin-left: var(--spacing-xs);
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
.prose .footnote-backref:hover {
|
|
1127
|
+
text-decoration: underline;
|
|
1128
|
+
}
|
|
1129
|
+
|
|
831
1130
|
/* ===== Empty State ===== */
|
|
832
1131
|
.empty-message {
|
|
833
1132
|
text-align: center;
|
|
@@ -325,6 +325,10 @@ img {
|
|
|
325
325
|
font-weight: 600;
|
|
326
326
|
margin: 0 0 var(--spacing-xs);
|
|
327
327
|
line-height: 1.4;
|
|
328
|
+
display: flex;
|
|
329
|
+
align-items: center;
|
|
330
|
+
flex-wrap: wrap;
|
|
331
|
+
gap: var(--spacing-sm);
|
|
328
332
|
}
|
|
329
333
|
|
|
330
334
|
.post-card-title a {
|
|
@@ -378,6 +382,10 @@ img {
|
|
|
378
382
|
letter-spacing: -0.02em;
|
|
379
383
|
margin: 0 0 var(--spacing-md);
|
|
380
384
|
line-height: 1.3;
|
|
385
|
+
display: flex;
|
|
386
|
+
align-items: center;
|
|
387
|
+
flex-wrap: wrap;
|
|
388
|
+
gap: var(--spacing-sm);
|
|
381
389
|
}
|
|
382
390
|
|
|
383
391
|
.post-meta {
|
|
@@ -547,12 +555,29 @@ img {
|
|
|
547
555
|
font-size: 0.875rem;
|
|
548
556
|
}
|
|
549
557
|
|
|
550
|
-
|
|
551
|
-
|
|
558
|
+
/* ===== Draft Badge ===== */
|
|
559
|
+
.draft-badge {
|
|
560
|
+
display: inline-flex;
|
|
561
|
+
align-items: center;
|
|
562
|
+
padding: 0.125em 0.4em;
|
|
563
|
+
background: #f59e0b;
|
|
564
|
+
color: white;
|
|
565
|
+
font-size: 0.65rem;
|
|
566
|
+
font-weight: 600;
|
|
567
|
+
text-transform: uppercase;
|
|
568
|
+
letter-spacing: 0.05em;
|
|
569
|
+
border-radius: var(--radius-sm);
|
|
570
|
+
line-height: 1;
|
|
571
|
+
flex-shrink: 0;
|
|
552
572
|
}
|
|
553
573
|
|
|
554
|
-
.
|
|
555
|
-
|
|
574
|
+
[data-theme="dark"] .draft-badge {
|
|
575
|
+
background: #fbbf24;
|
|
576
|
+
color: #0a0a0a;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
.prose .draft-badge {
|
|
580
|
+
font-size: 0.6rem;
|
|
556
581
|
}
|
|
557
582
|
|
|
558
583
|
.tag-section {
|
|
@@ -771,6 +796,44 @@ img {
|
|
|
771
796
|
border-radius: var(--radius-md);
|
|
772
797
|
}
|
|
773
798
|
|
|
799
|
+
/* YouTube Embed Styles */
|
|
800
|
+
.prose .youtube-embed {
|
|
801
|
+
position: relative;
|
|
802
|
+
padding-bottom: 56.25%; /* 16:9 aspect ratio */
|
|
803
|
+
height: 0;
|
|
804
|
+
overflow: hidden;
|
|
805
|
+
margin: 1.25em 0;
|
|
806
|
+
border-radius: var(--radius-md);
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
.prose .youtube-embed iframe {
|
|
810
|
+
position: absolute;
|
|
811
|
+
top: 0;
|
|
812
|
+
left: 0;
|
|
813
|
+
width: 100%;
|
|
814
|
+
height: 100%;
|
|
815
|
+
border: 0;
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
/* Giphy Embed Styles */
|
|
819
|
+
.prose .giphy-embed {
|
|
820
|
+
position: relative;
|
|
821
|
+
padding-bottom: 100%; /* Giphy embeds are typically square */
|
|
822
|
+
height: 0;
|
|
823
|
+
overflow: hidden;
|
|
824
|
+
margin: 1.25em 0;
|
|
825
|
+
border-radius: var(--radius-md);
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
.prose .giphy-embed iframe {
|
|
829
|
+
position: absolute;
|
|
830
|
+
top: 0;
|
|
831
|
+
left: 0;
|
|
832
|
+
width: 100%;
|
|
833
|
+
height: 100%;
|
|
834
|
+
border: 0;
|
|
835
|
+
}
|
|
836
|
+
|
|
774
837
|
.prose a {
|
|
775
838
|
text-decoration: underline;
|
|
776
839
|
text-decoration-color: var(--color-border);
|
|
@@ -806,6 +869,240 @@ img {
|
|
|
806
869
|
font-weight: 600;
|
|
807
870
|
}
|
|
808
871
|
|
|
872
|
+
/* ===== Alert Boxes ===== */
|
|
873
|
+
.prose .markdown-alert {
|
|
874
|
+
margin: 1.25em 0;
|
|
875
|
+
padding: var(--spacing-md) var(--spacing-lg);
|
|
876
|
+
border-left: 3px solid;
|
|
877
|
+
border-radius: var(--radius-md);
|
|
878
|
+
background: var(--color-bg-alt);
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
.prose .markdown-alert-title {
|
|
882
|
+
display: flex;
|
|
883
|
+
align-items: center;
|
|
884
|
+
gap: var(--spacing-sm);
|
|
885
|
+
margin: 0 0 var(--spacing-sm) 0;
|
|
886
|
+
font-weight: 600;
|
|
887
|
+
font-style: normal;
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
.prose .markdown-alert-title svg {
|
|
891
|
+
flex-shrink: 0;
|
|
892
|
+
width: 16px;
|
|
893
|
+
height: 16px;
|
|
894
|
+
fill: currentColor;
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
/* Make SVG icons lighter in dark mode */
|
|
898
|
+
[data-theme="dark"] .prose .markdown-alert-title svg {
|
|
899
|
+
fill: currentColor;
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
.prose .markdown-alert p:last-child {
|
|
903
|
+
margin-bottom: 0;
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
/* Note Alert */
|
|
907
|
+
.prose .markdown-alert-note {
|
|
908
|
+
border-left-color: #0969da;
|
|
909
|
+
background: rgba(9, 105, 218, 0.08);
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
.prose .markdown-alert-note .markdown-alert-title {
|
|
913
|
+
color: #0969da;
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
[data-theme="dark"] .prose .markdown-alert-note {
|
|
917
|
+
background: rgba(9, 105, 218, 0.12);
|
|
918
|
+
border-left-color: #58a6ff;
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
[data-theme="dark"] .prose .markdown-alert-note .markdown-alert-title {
|
|
922
|
+
color: #58a6ff;
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
[data-theme="dark"] .prose .markdown-alert-note .markdown-alert-title svg {
|
|
926
|
+
fill: #58a6ff;
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
/* Tip Alert */
|
|
930
|
+
.prose .markdown-alert-tip {
|
|
931
|
+
border-left-color: #1a7f37;
|
|
932
|
+
background: rgba(26, 127, 55, 0.08);
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
.prose .markdown-alert-tip .markdown-alert-title {
|
|
936
|
+
color: #1a7f37;
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
[data-theme="dark"] .prose .markdown-alert-tip {
|
|
940
|
+
background: rgba(26, 127, 55, 0.12);
|
|
941
|
+
border-left-color: #3fb950;
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
[data-theme="dark"] .prose .markdown-alert-tip .markdown-alert-title {
|
|
945
|
+
color: #3fb950;
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
[data-theme="dark"] .prose .markdown-alert-tip .markdown-alert-title svg {
|
|
949
|
+
fill: #3fb950;
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
/* Important Alert */
|
|
953
|
+
.prose .markdown-alert-important {
|
|
954
|
+
border-left-color: #8250df;
|
|
955
|
+
background: rgba(130, 80, 223, 0.08);
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
.prose .markdown-alert-important .markdown-alert-title {
|
|
959
|
+
color: #8250df;
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
[data-theme="dark"] .prose .markdown-alert-important {
|
|
963
|
+
background: rgba(130, 80, 223, 0.12);
|
|
964
|
+
border-left-color: #a371f7;
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
[data-theme="dark"] .prose .markdown-alert-important .markdown-alert-title {
|
|
968
|
+
color: #a371f7;
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
[data-theme="dark"] .prose .markdown-alert-important .markdown-alert-title svg {
|
|
972
|
+
fill: #a371f7;
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
/* Warning Alert */
|
|
976
|
+
.prose .markdown-alert-warning {
|
|
977
|
+
border-left-color: #9a6700;
|
|
978
|
+
background: rgba(154, 103, 0, 0.08);
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
.prose .markdown-alert-warning .markdown-alert-title {
|
|
982
|
+
color: #9a6700;
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
[data-theme="dark"] .prose .markdown-alert-warning {
|
|
986
|
+
background: rgba(154, 103, 0, 0.12);
|
|
987
|
+
border-left-color: #d29922;
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
[data-theme="dark"] .prose .markdown-alert-warning .markdown-alert-title {
|
|
991
|
+
color: #d29922;
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
[data-theme="dark"] .prose .markdown-alert-warning .markdown-alert-title svg {
|
|
995
|
+
fill: #d29922;
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
/* Caution Alert */
|
|
999
|
+
.prose .markdown-alert-caution {
|
|
1000
|
+
border-left-color: #cf222e;
|
|
1001
|
+
background: rgba(207, 34, 46, 0.08);
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
.prose .markdown-alert-caution .markdown-alert-title {
|
|
1005
|
+
color: #cf222e;
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
[data-theme="dark"] .prose .markdown-alert-caution {
|
|
1009
|
+
background: rgba(207, 34, 46, 0.12);
|
|
1010
|
+
border-left-color: #f85149;
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
[data-theme="dark"] .prose .markdown-alert-caution .markdown-alert-title {
|
|
1014
|
+
color: #f85149;
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
[data-theme="dark"] .prose .markdown-alert-caution .markdown-alert-title svg {
|
|
1018
|
+
fill: #f85149;
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
/* ===== Task Lists (Checkboxes) ===== */
|
|
1022
|
+
.prose ul.contains-task-list,
|
|
1023
|
+
.prose ol.contains-task-list {
|
|
1024
|
+
list-style: none;
|
|
1025
|
+
padding-left: 0;
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
.prose .task-list-item {
|
|
1029
|
+
display: flex;
|
|
1030
|
+
align-items: flex-start;
|
|
1031
|
+
gap: var(--spacing-sm);
|
|
1032
|
+
margin-bottom: 0.35em;
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
.prose .task-list-item input[type="checkbox"] {
|
|
1036
|
+
margin-top: 0.2em;
|
|
1037
|
+
cursor: pointer;
|
|
1038
|
+
width: 1em;
|
|
1039
|
+
height: 1em;
|
|
1040
|
+
flex-shrink: 0;
|
|
1041
|
+
accent-color: var(--color-primary);
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
.prose .task-list-item input[type="checkbox"]:checked {
|
|
1045
|
+
accent-color: var(--color-primary);
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
/* ===== Strikethrough ===== */
|
|
1049
|
+
.prose del,
|
|
1050
|
+
.prose s {
|
|
1051
|
+
text-decoration: line-through;
|
|
1052
|
+
text-decoration-color: var(--color-text-muted);
|
|
1053
|
+
opacity: 0.7;
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
/* ===== Footnotes ===== */
|
|
1057
|
+
.prose section[data-footnotes],
|
|
1058
|
+
.prose .footnotes {
|
|
1059
|
+
margin-top: 2em;
|
|
1060
|
+
padding-top: var(--spacing-lg);
|
|
1061
|
+
border-top: 1px solid var(--color-border);
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
.prose section[data-footnotes] h2,
|
|
1065
|
+
.prose .footnotes h2 {
|
|
1066
|
+
font-size: 0.95rem;
|
|
1067
|
+
font-weight: 600;
|
|
1068
|
+
margin-bottom: var(--spacing-md);
|
|
1069
|
+
color: var(--color-text-muted);
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1072
|
+
.prose section[data-footnotes] ol,
|
|
1073
|
+
.prose .footnotes ol {
|
|
1074
|
+
padding-left: 1.5em;
|
|
1075
|
+
font-size: 0.9rem;
|
|
1076
|
+
color: var(--color-text-muted);
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
.prose section[data-footnotes] li,
|
|
1080
|
+
.prose .footnotes li {
|
|
1081
|
+
margin-bottom: var(--spacing-sm);
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
.prose .footnote-ref {
|
|
1085
|
+
font-size: 0.85em;
|
|
1086
|
+
vertical-align: super;
|
|
1087
|
+
text-decoration: none;
|
|
1088
|
+
color: var(--color-primary);
|
|
1089
|
+
margin-left: 0.2em;
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
.prose .footnote-ref:hover {
|
|
1093
|
+
text-decoration: underline;
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
.prose .footnote-backref {
|
|
1097
|
+
text-decoration: none;
|
|
1098
|
+
color: var(--color-primary);
|
|
1099
|
+
margin-left: var(--spacing-xs);
|
|
1100
|
+
}
|
|
1101
|
+
|
|
1102
|
+
.prose .footnote-backref:hover {
|
|
1103
|
+
text-decoration: underline;
|
|
1104
|
+
}
|
|
1105
|
+
|
|
809
1106
|
/* ===== Empty State ===== */
|
|
810
1107
|
.empty-message {
|
|
811
1108
|
text-align: center;
|
package/lib/build.js
CHANGED
|
@@ -201,6 +201,15 @@ export async function build(options = {}) {
|
|
|
201
201
|
// Load configuration
|
|
202
202
|
const config = loadConfig(options.rootDir || process.cwd());
|
|
203
203
|
|
|
204
|
+
// Only show drafts in dev mode if explicitly enabled in config
|
|
205
|
+
// For production builds, always disable showDrafts
|
|
206
|
+
if (!options.devMode) {
|
|
207
|
+
if (config.server) {
|
|
208
|
+
config.server.showDrafts = false;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
// If devMode is true, use the config value (which defaults to false)
|
|
212
|
+
|
|
204
213
|
// Clean output directory if requested
|
|
205
214
|
if (options.clean !== false) {
|
|
206
215
|
cleanOutput(config);
|
package/lib/config.js
CHANGED
package/lib/content.js
CHANGED
|
@@ -120,6 +120,130 @@ marked.setOptions({
|
|
|
120
120
|
breaks: false
|
|
121
121
|
});
|
|
122
122
|
|
|
123
|
+
/**
|
|
124
|
+
* Extract YouTube video ID from various URL formats
|
|
125
|
+
* Supports:
|
|
126
|
+
* - https://www.youtube.com/watch?v=VIDEO_ID
|
|
127
|
+
* - https://youtu.be/VIDEO_ID
|
|
128
|
+
* - https://www.youtube.com/embed/VIDEO_ID
|
|
129
|
+
* - https://youtube.com/watch?v=VIDEO_ID
|
|
130
|
+
* - VIDEO_ID (if it's just an 11-character alphanumeric string)
|
|
131
|
+
*/
|
|
132
|
+
function extractYouTubeId(url) {
|
|
133
|
+
if (!url) return null;
|
|
134
|
+
|
|
135
|
+
// If it's just a video ID (11 characters, alphanumeric)
|
|
136
|
+
if (/^[a-zA-Z0-9_-]{11}$/.test(url)) {
|
|
137
|
+
return url;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Match various YouTube URL patterns
|
|
141
|
+
const patterns = [
|
|
142
|
+
/(?:youtube\.com\/watch\?v=|youtu\.be\/|youtube\.com\/embed\/)([a-zA-Z0-9_-]{11})/,
|
|
143
|
+
/youtube\.com\/.*[?&]v=([a-zA-Z0-9_-]{11})/
|
|
144
|
+
];
|
|
145
|
+
|
|
146
|
+
for (const pattern of patterns) {
|
|
147
|
+
const match = url.match(pattern);
|
|
148
|
+
if (match && match[1]) {
|
|
149
|
+
return match[1];
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Convert YouTube URLs in HTML to responsive embeds
|
|
158
|
+
*/
|
|
159
|
+
function embedYouTubeVideos(html) {
|
|
160
|
+
if (!html) return html;
|
|
161
|
+
|
|
162
|
+
// Pattern to match YouTube links in HTML
|
|
163
|
+
// Matches: <a href="...youtube...">...</a>
|
|
164
|
+
const linkPattern = /<a\s+[^>]*href=["']([^"']*youtube[^"']*)["'][^>]*>([^<]*)<\/a>/gi;
|
|
165
|
+
|
|
166
|
+
return html.replace(linkPattern, (match, url, linkText) => {
|
|
167
|
+
const videoId = extractYouTubeId(url);
|
|
168
|
+
if (videoId) {
|
|
169
|
+
// Return responsive YouTube embed
|
|
170
|
+
return `<div class="youtube-embed"><iframe src="https://www.youtube.com/embed/${videoId}" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></div>`;
|
|
171
|
+
}
|
|
172
|
+
return match; // Return original if not a valid YouTube URL
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Extract Giphy GIF ID from various URL formats
|
|
178
|
+
* Supports:
|
|
179
|
+
* - https://giphy.com/gifs/ID
|
|
180
|
+
* - https://gph.is/g/ID
|
|
181
|
+
* - https://giphy.com/embed/ID
|
|
182
|
+
* - https://media.giphy.com/media/ID/giphy.gif (extracts ID)
|
|
183
|
+
*/
|
|
184
|
+
function extractGiphyId(url) {
|
|
185
|
+
if (!url) return null;
|
|
186
|
+
|
|
187
|
+
// Match Giphy URL patterns
|
|
188
|
+
const patterns = [
|
|
189
|
+
/giphy\.com\/gifs\/([a-zA-Z0-9]+)/,
|
|
190
|
+
/giphy\.com\/embed\/([a-zA-Z0-9]+)/,
|
|
191
|
+
/gph\.is\/g\/([a-zA-Z0-9]+)/,
|
|
192
|
+
/media\.giphy\.com\/media\/([a-zA-Z0-9]+)\//
|
|
193
|
+
];
|
|
194
|
+
|
|
195
|
+
for (const pattern of patterns) {
|
|
196
|
+
const match = url.match(pattern);
|
|
197
|
+
if (match && match[1]) {
|
|
198
|
+
return match[1];
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Convert Giphy URLs in HTML to responsive embeds
|
|
207
|
+
*/
|
|
208
|
+
function embedGiphyGifs(html) {
|
|
209
|
+
if (!html) return html;
|
|
210
|
+
|
|
211
|
+
// Pattern to match Giphy links in HTML
|
|
212
|
+
const linkPattern = /<a\s+[^>]*href=["']([^"']*giphy[^"']*)["'][^>]*>([^<]*)<\/a>/gi;
|
|
213
|
+
|
|
214
|
+
return html.replace(linkPattern, (match, url, linkText) => {
|
|
215
|
+
const gifId = extractGiphyId(url);
|
|
216
|
+
if (gifId) {
|
|
217
|
+
// Return responsive Giphy embed
|
|
218
|
+
return `<div class="giphy-embed"><iframe src="https://giphy.com/embed/${gifId}" frameBorder="0" class="giphy-embed" allowFullScreen></iframe></div>`;
|
|
219
|
+
}
|
|
220
|
+
return match;
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// Override the link renderer to handle YouTube URLs
|
|
225
|
+
const renderer = marked.getRenderer();
|
|
226
|
+
const originalLink = renderer.link.bind(renderer);
|
|
227
|
+
|
|
228
|
+
renderer.link = (token) => {
|
|
229
|
+
const videoId = extractYouTubeId(token.href);
|
|
230
|
+
|
|
231
|
+
if (videoId) {
|
|
232
|
+
// Return responsive YouTube embed instead of a link
|
|
233
|
+
return `<div class="youtube-embed"><iframe src="https://www.youtube.com/embed/${videoId}" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></div>`;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
const gifId = extractGiphyId(token.href);
|
|
237
|
+
|
|
238
|
+
if (gifId) {
|
|
239
|
+
// Return responsive Giphy embed instead of a link
|
|
240
|
+
return `<div class="giphy-embed"><iframe src="https://giphy.com/embed/${gifId}" frameBorder="0" class="giphy-embed" allowFullScreen></iframe></div>`;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Use default link rendering for non-YouTube/Giphy links
|
|
244
|
+
return originalLink(token);
|
|
245
|
+
};
|
|
246
|
+
|
|
123
247
|
/**
|
|
124
248
|
* Generate a URL-friendly slug from a string
|
|
125
249
|
*/
|
|
@@ -172,7 +296,11 @@ export function parseContent(filePath) {
|
|
|
172
296
|
const { data: frontMatter, content: markdown } = matter(content);
|
|
173
297
|
|
|
174
298
|
// Parse markdown to HTML
|
|
175
|
-
|
|
299
|
+
let html = marked.parse(markdown);
|
|
300
|
+
|
|
301
|
+
// Convert any remaining YouTube/Giphy links to embeds (handles autolinked URLs)
|
|
302
|
+
html = embedYouTubeVideos(html);
|
|
303
|
+
html = embedGiphyGifs(html);
|
|
176
304
|
|
|
177
305
|
// Get slug from front matter or filename
|
|
178
306
|
const slug = frontMatter.slug || getSlugFromFilename(filePath);
|
|
@@ -283,7 +411,15 @@ export function loadCollection(config, collectionName) {
|
|
|
283
411
|
return null;
|
|
284
412
|
}
|
|
285
413
|
})
|
|
286
|
-
.filter(item =>
|
|
414
|
+
.filter(item => {
|
|
415
|
+
if (item === null) return false;
|
|
416
|
+
// Include drafts if showDrafts is enabled in server config
|
|
417
|
+
if (item.draft && config.server?.showDrafts) {
|
|
418
|
+
return true;
|
|
419
|
+
}
|
|
420
|
+
// Otherwise, exclude drafts
|
|
421
|
+
return !item.draft;
|
|
422
|
+
});
|
|
287
423
|
|
|
288
424
|
// Sort items
|
|
289
425
|
const sortBy = collectionConfig.sortBy || 'date';
|
package/lib/server.js
CHANGED
|
@@ -188,7 +188,7 @@ function setupWatcher(config, wss) {
|
|
|
188
188
|
console.log('š Rebuilding...\n');
|
|
189
189
|
|
|
190
190
|
try {
|
|
191
|
-
await build({ clean: false, rootDir: config.rootDir });
|
|
191
|
+
await build({ clean: false, rootDir: config.rootDir, devMode: true });
|
|
192
192
|
notifyReload(wss);
|
|
193
193
|
} catch (err) {
|
|
194
194
|
console.error('ā Rebuild failed:', err.message);
|
|
@@ -213,8 +213,8 @@ export async function startServer(options = {}) {
|
|
|
213
213
|
|
|
214
214
|
console.log('\nā” Sia - Development Server\n');
|
|
215
215
|
|
|
216
|
-
// Initial build
|
|
217
|
-
await build({ clean: true, rootDir: config.rootDir });
|
|
216
|
+
// Initial build with devMode enabled to show drafts if configured
|
|
217
|
+
await build({ clean: true, rootDir: config.rootDir, devMode: true });
|
|
218
218
|
|
|
219
219
|
// Create servers
|
|
220
220
|
const httpServer = createHttpServer(config, wsPort);
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -131,8 +131,18 @@ pagination:
|
|
|
131
131
|
|
|
132
132
|
server:
|
|
133
133
|
port: 3000
|
|
134
|
+
showDrafts: false # Set to true to show draft posts in dev server
|
|
134
135
|
```
|
|
135
136
|
|
|
137
|
+
### Server Configuration
|
|
138
|
+
|
|
139
|
+
| Option | Description | Default |
|
|
140
|
+
|-------|-------------|---------|
|
|
141
|
+
| `port` | Port number for development server | `3000` |
|
|
142
|
+
| `showDrafts` | Show draft posts when using `sia dev` | `false` |
|
|
143
|
+
|
|
144
|
+
When `showDrafts` is set to `true`, draft posts (posts with `draft: true` in front matter) will be included in the development server build. This is useful for previewing draft content locally. Drafts are always excluded from production builds.
|
|
145
|
+
|
|
136
146
|
## Front Matter
|
|
137
147
|
|
|
138
148
|
Each markdown file can have YAML front matter:
|
|
@@ -158,7 +168,7 @@ excerpt: "Custom excerpt text"
|
|
|
158
168
|
| `tags` | Array of tags |
|
|
159
169
|
| `layout` | Template to use |
|
|
160
170
|
| `permalink` | Custom URL |
|
|
161
|
-
| `draft` | If true, excluded from build |
|
|
171
|
+
| `draft` | If true, excluded from build (unless `server.showDrafts` is enabled) |
|
|
162
172
|
| `excerpt` | Custom excerpt |
|
|
163
173
|
|
|
164
174
|
## Markdown Features
|
|
@@ -248,6 +258,55 @@ Plain URLs are automatically converted to clickable links:
|
|
|
248
258
|
Visit https://example.com for more info.
|
|
249
259
|
```
|
|
250
260
|
|
|
261
|
+
### Media Embeds
|
|
262
|
+
|
|
263
|
+
Sia automatically converts YouTube and Giphy URLs into responsive embeds.
|
|
264
|
+
|
|
265
|
+
#### YouTube Videos
|
|
266
|
+
|
|
267
|
+
YouTube videos can be embedded using any of these methods:
|
|
268
|
+
|
|
269
|
+
**As a markdown link:**
|
|
270
|
+
```markdown
|
|
271
|
+
[Watch this video](https://www.youtube.com/watch?v=dQw4w9WgXcQ)
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
**As a plain URL (auto-linked):**
|
|
275
|
+
```markdown
|
|
276
|
+
https://www.youtube.com/watch?v=dQw4w9WgXcQ
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
**Using short URL format:**
|
|
280
|
+
```markdown
|
|
281
|
+
https://youtu.be/dQw4w9WgXcQ
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
All of these formats are automatically converted to responsive YouTube embeds.
|
|
285
|
+
|
|
286
|
+
#### Giphy GIFs
|
|
287
|
+
|
|
288
|
+
Giphy GIFs can be embedded in two ways:
|
|
289
|
+
|
|
290
|
+
**As a direct image link (standard markdown):**
|
|
291
|
+
```markdown
|
|
292
|
+

|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
**As a Giphy share URL (auto-embedded):**
|
|
296
|
+
```markdown
|
|
297
|
+
[Check this out](https://giphy.com/gifs/ID)
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
Or just paste the URL:
|
|
301
|
+
```markdown
|
|
302
|
+
https://giphy.com/gifs/ID
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
Giphy share URLs are automatically converted to responsive embeds. Supported formats include:
|
|
306
|
+
- `https://giphy.com/gifs/ID`
|
|
307
|
+
- `https://gph.is/g/ID`
|
|
308
|
+
- `https://giphy.com/embed/ID`
|
|
309
|
+
|
|
251
310
|
### GitHub Flavored Markdown
|
|
252
311
|
|
|
253
312
|
Full GFM support including:
|