Compare commits

..
Author SHA1 Message Date
Rsclub2_2 fcd8b34135 fix: resolve the open CodeQL alerts
Strip HTML tags and XML comments until the text no longer changes, so that
nested input cannot reassemble a tag or comment after a single pass
(js/incomplete-multi-character-sanitization in website/.eleventy.js and
website/scripts/validate-version-info.js).

Limit the GITHUB_TOKEN of the PR compile check and the test version-XML
workflow to read access (actions/missing-workflow-permissions).

Claude-Session: https://claude.ai/code/session_01FJBfPYm6rCH4zD6T7bcC7Y
2026-10-26 10:07:44 +01:00
14 changed files with 241 additions and 313 deletions

No files matched your search

@@ -55,47 +55,45 @@ class CompactControlsVisualRenderingTest(@param:TempDir private val tempDir: Pat
} }
val filters = StationFilterState() val filters = StationFilterState()
return onEventThread { val scene = ImageComposeScene(width = 1366, height = 380, density = Density(scale)) {
val scene = ImageComposeScene(width = 1366, height = 380, density = Density(scale)) { Kst4ContestTheme(darkMode = darkMode, baseFontSizeSp = 12f) {
Kst4ContestTheme(darkMode = darkMode, baseFontSizeSp = 12f) { Surface(
Surface( modifier = Modifier.fillMaxSize(),
modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background,
color = MaterialTheme.colorScheme.background, ) {
) { Column(Modifier.padding(4.dp)) {
Column(Modifier.padding(4.dp)) { TimelineView(
TimelineView( state = TimelineState(),
state = TimelineState(), onCandidateClicked = {},
onCandidateClicked = {}, modifier = Modifier.fillMaxWidth(),
modifier = Modifier.fillMaxWidth(), )
) Spacer(Modifier.height(8.dp))
Spacer(Modifier.height(8.dp)) StationFilterBar(
StationFilterBar( filters = filters,
filters = filters, activeBands = EnumSet.of(Band.B_144, Band.B_432, Band.B_1296),
activeBands = EnumSet.of(Band.B_144, Band.B_432, Band.B_1296), reachability = ReachabilityState(
reachability = ReachabilityState( EnumSet.of(Band.B_144, Band.B_432, Band.B_1296),
EnumSet.of(Band.B_144, Band.B_432, Band.B_1296), ),
), onChanged = {},
onChanged = {}, )
) Spacer(Modifier.height(12.dp))
Spacer(Modifier.height(12.dp)) ChatInputRow(
ChatInputRow( state = chatInputState,
state = chatInputState, prefs = preferences,
prefs = preferences, ownQrgMain = ObservedValue(preferences.getMYQRGFirstCat()),
ownQrgMain = ObservedValue(preferences.getMYQRGFirstCat()), ownQrgSecond = ObservedValue(preferences.getMYQRGSecondCat()),
ownQrgSecond = ObservedValue(preferences.getMYQRGSecondCat()), antennaQtf = ObservedValue(preferences.getActualQTF()),
antennaQtf = ObservedValue(preferences.getActualQTF()), antennaQtf2 = ObservedValue(preferences.getActualQTF2()),
antennaQtf2 = ObservedValue(preferences.getActualQTF2()), so2rEnabled = false,
so2rEnabled = false, )
)
}
} }
} }
} }
try { }
scene.render().encodeToData()!!.bytes return try {
} finally { scene.render().encodeToData()!!.bytes
scene.close() } finally {
} scene.close()
} }
} }
@@ -1,37 +0,0 @@
package kst4contest.view.compose
import java.awt.EventQueue
import java.lang.reflect.InvocationTargetException
/*
* An ImageComposeScene must live on the AWT event thread, the thread the application renders
* on. Compose Multiplatform 1.8.2 sends the global snapshot notifications there
* (GlobalSnapshotManager), and doing so takes two locks in the opposite order from a render
* on any other thread:
*
* - the render holds the scene's FlushCoroutineDispatcher runLock while a task it runs
* (here LazyListState.scrollToItem) measures and wants the SnapshotStateObserver's
* observedScopeMapsLock;
* - the event thread holds observedScopeMapsLock in drainChanges while a derived state it
* re-reads wakes a snapshotFlow collector of that scene, whose dispatch wants runLock.
*
* Both waited forever in CI runs 40252077018, 40252089738 and 40299943329; the thread dump of
* the last one shows both stacks. On one thread the two monitors are simply re-entered, which
* is why the application never hangs this way.
*/
/**
* Runs [block] on the AWT event thread, waits for it and returns its result. Whatever
* [block] throws is rethrown here unwrapped, so a failed assertion still reads as one.
*/
internal fun <T> onEventThread(block: () -> T): T {
if (EventQueue.isDispatchThread()) return block()
var result: Result<T>? = null
try {
EventQueue.invokeAndWait { result = runCatching(block) }
} catch (wrapped: InvocationTargetException) {
throw wrapped.cause ?: wrapped
}
return result!!.getOrThrow()
}
@@ -84,39 +84,37 @@ class SelectedStationMessageUiVisualRenderingTest {
replaceRows(listOf(message(member("DL1ABC", 2), member("DL2XYZ", 2), "pse sked"))) replaceRows(listOf(message(member("DL1ABC", 2), member("DL2XYZ", 2), "pse sked")))
} }
return onEventThread { val scene = ImageComposeScene(width = 1366, height = windowHeight, density = Density(scale)) {
val scene = ImageComposeScene(width = 1366, height = windowHeight, density = Density(scale)) { Kst4ContestTheme(darkMode = darkMode, baseFontSizeSp = 12f) {
Kst4ContestTheme(darkMode = darkMode, baseFontSizeSp = 12f) { Surface(
Surface( modifier = Modifier.fillMaxSize(),
modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background,
color = MaterialTheme.colorScheme.background, ) {
) { Row(Modifier.fillMaxSize().padding(6.dp)) {
Row(Modifier.fillMaxSize().padding(6.dp)) { MessageTabs(
MessageTabs( publicMessages = publicMessages,
publicMessages = publicMessages, clusterMessages = clusterTable(),
clusterMessages = clusterTable(), qsoOfTheOther = qsoMessages,
qsoOfTheOther = qsoMessages, modifier = Modifier.weight(1f),
modifier = Modifier.weight(1f), )
) SelectedStationPanel(
SelectedStationPanel( state = selectedState,
state = selectedState, messages = selectedMessages,
messages = selectedMessages, activeBands = EnumSet.of(Band.B_144, Band.B_432, Band.B_1296),
activeBands = EnumSet.of(Band.B_144, Band.B_432, Band.B_1296), openInBrowser = Consumer {},
openInBrowser = Consumer {}, onShowOnMap = {},
onShowOnMap = {}, onShowPathInAirScout = {},
onShowPathInAirScout = {}, modifier = Modifier.width(panelWidth).padding(start = 6.dp),
modifier = Modifier.width(panelWidth).padding(start = 6.dp), )
)
}
} }
} }
} }
}
try { return try {
scene.render().encodeToData()!!.bytes scene.render().encodeToData()!!.bytes
} finally { } finally {
scene.close() scene.close()
}
} }
} }
@@ -87,64 +87,62 @@ class StationWorkspaceVisualRenderingTest {
RowKeys.byReference<ChatMessage>(), RowKeys.byReference<ChatMessage>(),
) )
return onEventThread { val scene = ImageComposeScene(
val scene = ImageComposeScene( width = 1366,
width = 1366, height = scenario.height,
height = scenario.height, density = Density(scale),
density = Density(scale), ) {
) { Kst4ContestTheme(darkMode = darkMode, baseFontSizeSp = 12f) {
Kst4ContestTheme(darkMode = darkMode, baseFontSizeSp = 12f) { Surface(
Surface( modifier = Modifier.fillMaxSize(),
modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background,
color = MaterialTheme.colorScheme.background, ) {
Box(Modifier.fillMaxSize()) {
Column(
Modifier
.width(scenario.width.dp)
.fillMaxHeight()
.align(Alignment.TopEnd)
.padding(4.dp),
) { ) {
Box(Modifier.fillMaxSize()) { StationFilterBar(
Column( filters = StationFilterState(),
Modifier activeBands = EnumSet.of(Band.B_144, Band.B_432),
.width(scenario.width.dp) reachability = ReachabilityState(EnumSet.of(Band.B_144, Band.B_432)),
.fillMaxHeight() onChanged = {},
.align(Alignment.TopEnd) )
.padding(4.dp), DataTableView(
) { state = stations,
StationFilterBar( modifier = Modifier.weight(0.45f),
filters = StationFilterState(), emphasizeCell = { member, column ->
activeBands = EnumSet.of(Band.B_144, Band.B_432), column.id == "callsign" && newJoined.isRecent(member)
reachability = ReachabilityState(EnumSet.of(Band.B_144, Band.B_432)), },
onChanged = {}, )
) TopPriorityBar(
DataTableView( state = priority,
state = stations, newJoined = newJoined,
modifier = Modifier.weight(0.45f), onShowMore = {},
emphasizeCell = { member, column -> )
column.id == "callsign" && newJoined.isRecent(member) SelectedStationPanel(
}, state = selected,
) messages = selectedMessages,
TopPriorityBar( activeBands = EnumSet.of(Band.B_144, Band.B_432),
state = priority, contentSplitter = SplitterState(2, doubleArrayOf(0.48)) {},
newJoined = newJoined, openInBrowser = Consumer {},
onShowMore = {}, onShowOnMap = {},
) onShowPathInAirScout = {},
SelectedStationPanel( modifier = Modifier.weight(0.55f),
state = selected, )
messages = selectedMessages, }
activeBands = EnumSet.of(Band.B_144, Band.B_432),
contentSplitter = SplitterState(2, doubleArrayOf(0.48)) {},
openInBrowser = Consumer {},
onShowOnMap = {},
onShowPathInAirScout = {},
modifier = Modifier.weight(0.55f),
)
}
}
} }
} }
} }
}
try { return try {
scene.render().encodeToData()!!.bytes scene.render().encodeToData()!!.bytes
} finally { } finally {
scene.close() scene.close()
}
} }
} }
@@ -32,20 +32,18 @@ class TopPriorityCandidatesWindowTest {
/** Runs [block] against a rendered list of [twoCandidates] and reports what it picked. */ /** Runs [block] against a rendered list of [twoCandidates] and reports what it picked. */
private fun picking(block: (ImageComposeScene) -> Unit): String? { private fun picking(block: (ImageComposeScene) -> Unit): String? {
var picked: String? = null var picked: String? = null
onEventThread { val scene = ImageComposeScene(width = 360, height = 500, density = Density(1f)) {
val scene = ImageComposeScene(width = 360, height = 500, density = Density(1f)) { TopPriorityCandidatesWindow.CandidateListForTest(twoCandidates) {
TopPriorityCandidatesWindow.CandidateListForTest(twoCandidates) { picked = it.displayCallSign
picked = it.displayCallSign
}
}
try {
scene.render()
block(scene)
scene.render()
} finally {
scene.close()
} }
} }
try {
scene.render()
block(scene)
scene.render()
} finally {
scene.close()
}
return picked return picked
} }
@@ -80,15 +78,13 @@ class TopPriorityCandidatesWindowTest {
@Test @Test
fun `the list renders with candidates and without`() { fun `the list renders with candidates and without`() {
listOf(emptyList(), twoCandidates).forEach { ranking -> listOf(emptyList(), twoCandidates).forEach { ranking ->
onEventThread { val scene = ImageComposeScene(width = 360, height = 500, density = Density(1f)) {
val scene = ImageComposeScene(width = 360, height = 500, density = Density(1f)) { TopPriorityCandidatesWindow.CandidateListForTest(ranking) { }
TopPriorityCandidatesWindow.CandidateListForTest(ranking) { } }
} try {
try { scene.render()
scene.render() } finally {
} finally { scene.close()
scene.close()
}
} }
} }
} }
@@ -4,7 +4,6 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.ui.ImageComposeScene import androidx.compose.ui.ImageComposeScene
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.Density import androidx.compose.ui.unit.Density
import kst4contest.view.compose.onEventThread
import kst4contest.view.map.MapCallsignRawSnapshot import kst4contest.view.map.MapCallsignRawSnapshot
import kst4contest.view.map.MapViewport import kst4contest.view.map.MapViewport
import kst4contest.view.map.TileFetcher import kst4contest.view.map.TileFetcher
@@ -72,29 +71,27 @@ class ComposeStationMapDrawingTest {
workedGrossFields: Set<String> = emptySet(), workedGrossFields: Set<String> = emptySet(),
darkMode: Boolean = true, darkMode: Boolean = true,
): BufferedImage { ): BufferedImage {
return onEventThread { val scene = ImageComposeScene(canvasWidth, canvasHeight, Density(1f)) {
val scene = ImageComposeScene(canvasWidth, canvasHeight, Density(1f)) { ComposeStationMap(
ComposeStationMap( markers = markers,
markers = markers, tileFetcher = offlineTileFetcher,
tileFetcher = offlineTileFetcher, mapState = MapState(zoom = zoom, centerLon = 10.0, centerLat = 51.0),
mapState = MapState(zoom = zoom, centerLon = 10.0, centerLat = 51.0), groupingEnabled = false,
groupingEnabled = false, selectedMarkerCallsign = null,
selectedMarkerCallsign = null, ownLocator6 = ownLocator6,
ownLocator6 = ownLocator6, antennaAzimuthDeg = 90.0,
antennaAzimuthDeg = 90.0, antennaBeamWidthDeg = 0.0,
antennaBeamWidthDeg = 0.0, maxQrbKm = 0.0,
maxQrbKm = 0.0, onMarkerClicked = null,
onMarkerClicked = null, workedGrossFields = workedGrossFields,
workedGrossFields = workedGrossFields, darkMode = darkMode,
darkMode = darkMode, modifier = Modifier.fillMaxSize(),
modifier = Modifier.fillMaxSize(), )
) }
} try {
try { return ImageIO.read(ByteArrayInputStream(scene.render().encodeToData()!!.bytes))
ImageIO.read(ByteArrayInputStream(scene.render().encodeToData()!!.bytes)) } finally {
} finally { scene.close()
scene.close()
}
} }
} }
@@ -4,7 +4,6 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.ui.ImageComposeScene import androidx.compose.ui.ImageComposeScene
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.Density import androidx.compose.ui.unit.Density
import kst4contest.view.compose.onEventThread
import kst4contest.view.map.MapCallsignRawSnapshot import kst4contest.view.map.MapCallsignRawSnapshot
import kst4contest.view.map.TileFetcher import kst4contest.view.map.TileFetcher
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
@@ -34,32 +33,30 @@ class ComposeStationMapLayoutTest {
) )
private fun renderAt(widthPx: Int, heightPx: Int, zoom: Float) { private fun renderAt(widthPx: Int, heightPx: Int, zoom: Float) {
onEventThread { val scene = ImageComposeScene(
val scene = ImageComposeScene( width = widthPx,
width = widthPx, height = heightPx,
height = heightPx, density = Density(1f),
density = Density(1f), ) {
) { ComposeStationMap(
ComposeStationMap( markers = stations,
markers = stations, tileFetcher = TileFetcher(),
tileFetcher = TileFetcher(), mapState = MapState(zoom = zoom, centerLon = 10.0, centerLat = 51.0),
mapState = MapState(zoom = zoom, centerLon = 10.0, centerLat = 51.0), groupingEnabled = true,
groupingEnabled = true, selectedMarkerCallsign = "F5JMI",
selectedMarkerCallsign = "F5JMI", ownLocator6 = "JO50JP",
ownLocator6 = "JO50JP", antennaAzimuthDeg = 229.0,
antennaAzimuthDeg = 229.0, antennaBeamWidthDeg = 60.0,
antennaBeamWidthDeg = 60.0, maxQrbKm = 800.0,
maxQrbKm = 800.0, onMarkerClicked = null,
onMarkerClicked = null, darkMode = true,
darkMode = true, modifier = Modifier.fillMaxSize(),
modifier = Modifier.fillMaxSize(), )
) }
} try {
try { scene.render()
scene.render() } finally {
} finally { scene.close()
scene.close()
}
} }
} }
@@ -4,7 +4,6 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.ui.ImageComposeScene import androidx.compose.ui.ImageComposeScene
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.Density import androidx.compose.ui.unit.Density
import kst4contest.view.compose.onEventThread
import kst4contest.view.map.PathAnalysisResult import kst4contest.view.map.PathAnalysisResult
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
@@ -26,23 +25,21 @@ class PathAnalysisDetailsLayoutTest {
private val narrowWidthPx = 120 private val narrowWidthPx = 120
private fun renderAt(widthPx: Int, result: PathAnalysisResult?) { private fun renderAt(widthPx: Int, result: PathAnalysisResult?) {
onEventThread { val scene = ImageComposeScene(
val scene = ImageComposeScene( width = widthPx,
width = widthPx, height = 600,
height = 600, density = Density(1f),
density = Density(1f), ) {
) { PathAnalysisDetails(
PathAnalysisDetails( result = result,
result = result, darkMode = true,
darkMode = true, modifier = Modifier.fillMaxWidth(),
modifier = Modifier.fillMaxWidth(), )
) }
} try {
try { scene.render()
scene.render() } finally {
} finally { scene.close()
scene.close()
}
} }
} }
@@ -4,7 +4,6 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.ui.ImageComposeScene import androidx.compose.ui.ImageComposeScene
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.Density import androidx.compose.ui.unit.Density
import kst4contest.view.compose.onEventThread
import kst4contest.view.map.PathAnalysisResult import kst4contest.view.map.PathAnalysisResult
import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
@@ -32,20 +31,18 @@ class PathAnalysisDetailsWidthTest {
private val assessmentBackground = 0x33383E private val assessmentBackground = 0x33383E
private fun render(paneWidthPx: Int, heightPx: Int = 600): BufferedImage { private fun render(paneWidthPx: Int, heightPx: Int = 600): BufferedImage {
return onEventThread { val scene = ImageComposeScene(width = paneWidthPx, height = heightPx, density = Density(1f)) {
val scene = ImageComposeScene(width = paneWidthPx, height = heightPx, density = Density(1f)) { PathAnalysisDetails(
PathAnalysisDetails( result = PathAnalysisResult.loading("JO50JP", "JN24JB", "F5JMI"),
result = PathAnalysisResult.loading("JO50JP", "JN24JB", "F5JMI"), darkMode = true,
darkMode = true, modifier = Modifier.fillMaxWidth(),
modifier = Modifier.fillMaxWidth(), )
) }
} try {
try { val png = scene.render().encodeToData()!!.bytes
val png = scene.render().encodeToData()!!.bytes return ImageIO.read(ByteArrayInputStream(png))
ImageIO.read(ByteArrayInputStream(png)) } finally {
} finally { scene.close()
scene.close()
}
} }
} }
@@ -4,7 +4,6 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.ui.ImageComposeScene import androidx.compose.ui.ImageComposeScene
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.Density import androidx.compose.ui.unit.Density
import kst4contest.view.compose.onEventThread
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
/** /**
@@ -19,19 +18,17 @@ import org.junit.jupiter.api.Test
class PathProfileChartLayoutTest { class PathProfileChartLayoutTest {
private fun renderAt(widthPx: Int, heightPx: Int) { private fun renderAt(widthPx: Int, heightPx: Int) {
onEventThread { val scene = ImageComposeScene(
val scene = ImageComposeScene( width = widthPx,
width = widthPx, height = heightPx,
height = heightPx, density = Density(1f),
density = Density(1f), ) {
) { PathProfileChart(modifier = Modifier.fillMaxSize(), darkMode = true)
PathProfileChart(modifier = Modifier.fillMaxSize(), darkMode = true) }
} try {
try { scene.render()
scene.render() } finally {
} finally { scene.close()
scene.close()
}
} }
} }
@@ -15,7 +15,6 @@ import androidx.compose.ui.unit.dp
import kst4contest.view.compose.SplitterOrientation import kst4contest.view.compose.SplitterOrientation
import kst4contest.view.compose.SplitterPane import kst4contest.view.compose.SplitterPane
import kst4contest.view.compose.SplitterState import kst4contest.view.compose.SplitterState
import kst4contest.view.compose.onEventThread
import kst4contest.view.map.MapCallsignRawSnapshot import kst4contest.view.map.MapCallsignRawSnapshot
import kst4contest.view.map.PathAnalysisResult import kst4contest.view.map.PathAnalysisResult
import kst4contest.view.map.TileFetcher import kst4contest.view.map.TileFetcher
@@ -89,15 +88,13 @@ class StationMapBodyLayoutTest {
} }
private fun renderAt(widthPx: Int, heightPx: Int, pathAnalysisVisible: Boolean = true) { private fun renderAt(widthPx: Int, heightPx: Int, pathAnalysisVisible: Boolean = true) {
onEventThread { val scene = ImageComposeScene(width = widthPx, height = heightPx, density = Density(1f)) {
val scene = ImageComposeScene(width = widthPx, height = heightPx, density = Density(1f)) { Body(pathAnalysisVisible)
Body(pathAnalysisVisible) }
} try {
try { scene.render()
scene.render() } finally {
} finally { scene.close()
scene.close()
}
} }
} }
-7
View File
@@ -151,13 +151,6 @@ subprojects {
*/ */
systemProperty("junit.jupiter.execution.timeout.default", "2m") systemProperty("junit.jupiter.execution.timeout.default", "2m")
systemProperty("junit.jupiter.execution.timeout.thread.mode.default", "SEPARATE_THREAD") systemProperty("junit.jupiter.execution.timeout.thread.mode.default", "SEPARATE_THREAD")
/*
* The timed-out thread's stack shows where a test waits, not who it waits for: the
* rare CI hang in SelectedStationMessageUiVisualRenderingTest blocks on a monitor
* that another thread holds. On a timeout JUnit prints all threads to the test's
* standard output, which lands in its XML report (the test-results artifact).
*/
systemProperty("junit.jupiter.execution.timeout.threaddump.enabled", "true")
// The default short format prints only the first frame of each cause, which for a // The default short format prints only the first frame of each cause, which for a
// timed-out test is the line it hung in but not the call that blocked there. // timed-out test is the line it hung in but not the call that blocked there.
testLogging { testLogging {
+19 -19
View File
@@ -7,15 +7,15 @@
"": { "": {
"name": "kst4contest-website", "name": "kst4contest-website",
"version": "0.1.0", "version": "0.1.0",
"engines": {
"node": ">=18.19.1"
},
"dependencies": { "dependencies": {
"markdown-it": "^14.3.3", "markdown-it": "^14.3.0",
"markdown-it-anchor": "^9.2.0" "markdown-it-anchor": "^9.2.0"
}, },
"devDependencies": { "devDependencies": {
"@11ty/eleventy": "^3.0.0" "@11ty/eleventy": "^3.0.0"
},
"engines": {
"node": ">=18.19.1"
} }
}, },
"node_modules/@11ty/dependency-tree": { "node_modules/@11ty/dependency-tree": {
@@ -397,9 +397,9 @@
} }
}, },
"node_modules/brace-expansion": { "node_modules/brace-expansion": {
"version": "1.1.21", "version": "1.1.15",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz",
"integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -831,9 +831,9 @@
} }
}, },
"node_modules/gray-matter/node_modules/js-yaml": { "node_modules/gray-matter/node_modules/js-yaml": {
"version": "3.15.2", "version": "3.15.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.15.2.tgz", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.15.0.tgz",
"integrity": "sha512-6EuL879VkRA+1Cz578mKMiKvjPNEuk6+r1JaFzoSWejZmtf7xWbIyw1e3KkxlkzTIt9Taw6JBhEppG7utc1P+w==", "integrity": "sha512-ttBQIIQPDeLjpPOohtUdXuXUVoA2uIB6fEH9HyJ7234s5mBJ5wTx20njxplLZQgLaOfpmPQA7X2t5AX6tIPbog==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -1026,9 +1026,9 @@
} }
}, },
"node_modules/js-yaml": { "node_modules/js-yaml": {
"version": "4.3.2", "version": "4.3.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.2.tgz", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.0.tgz",
"integrity": "sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==", "integrity": "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {
@@ -1098,9 +1098,9 @@
} }
}, },
"node_modules/liquidjs": { "node_modules/liquidjs": {
"version": "10.30.0", "version": "10.27.1",
"resolved": "https://registry.npmjs.org/liquidjs/-/liquidjs-10.30.0.tgz", "resolved": "https://registry.npmjs.org/liquidjs/-/liquidjs-10.27.1.tgz",
"integrity": "sha512-Fw4wA+8CZsJkaeLEIlPE3AoponfjEZhj7FQvYNcAEcg7jNRik7mEMoaco382FBdrYlykVf6w4vClPNctz2OYjg==", "integrity": "sha512-ylE+1q2kSef1UxAyxqbyuWM3FRWS1v48JK1Y3CoW3bD6TSNXZh0+GsVnihujEpKyR+Jejx2aRAFfC3AHm9rElg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -1136,9 +1136,9 @@
} }
}, },
"node_modules/markdown-it": { "node_modules/markdown-it": {
"version": "14.3.3", "version": "14.3.0",
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.3.3.tgz", "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.3.0.tgz",
"integrity": "sha512-L//tDAkjTjJCU6pBUSBTgs3Kg4InVaZuUZog/b6V12UKhcDQ7S78877ibbCanRExwPuYP1CZD7Gd2dxSy1GXRg==", "integrity": "sha512-RCEsPjR+sr0x+AuYp601tKTkgFG4YEPLCzHST3cQ/fhlJkqAkz1L2/Qbp1j9qw5SBwQHFBoW8+hoN5xssOF0Tw==",
"funding": [ "funding": [
{ {
"type": "github", "type": "github",
+1 -1
View File
@@ -15,7 +15,7 @@
"@11ty/eleventy": "^3.0.0" "@11ty/eleventy": "^3.0.0"
}, },
"dependencies": { "dependencies": {
"markdown-it": "^14.3.3", "markdown-it": "^14.3.0",
"markdown-it-anchor": "^9.2.0" "markdown-it-anchor": "^9.2.0"
} }
} }