fix(multiframe): metadata handling of NM studies and loading order (#4540)
This commit is contained in:
parent
3b66867508
commit
71f06dcd3e
@ -5,8 +5,6 @@ server {
|
||||
root /usr/share/nginx/html;
|
||||
index index.html index.htm;
|
||||
try_files $uri $uri/ /index.html;
|
||||
add_header Cross-Origin-Opener-Policy same-origin;
|
||||
add_header Cross-Origin-Embedder-Policy require-corp;
|
||||
add_header Cross-Origin-Resource-Policy same-origin;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
|
||||
@ -7,8 +7,6 @@ server {
|
||||
root /usr/share/nginx/html;
|
||||
index index.html index.htm;
|
||||
try_files $uri $uri/ /index.html;
|
||||
add_header Cross-Origin-Opener-Policy same-origin;
|
||||
add_header Cross-Origin-Embedder-Policy require-corp;
|
||||
add_header Cross-Origin-Resource-Policy same-origin;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
|
||||
@ -57,10 +57,6 @@ if (!process.env.APP_CONFIG) {
|
||||
}
|
||||
|
||||
module.exports = (env, argv, { SRC_DIR, ENTRY }) => {
|
||||
if (!process.env.NODE_ENV) {
|
||||
throw new Error('process.env.NODE_ENV not set');
|
||||
}
|
||||
|
||||
const mode = NODE_ENV === 'production' ? 'production' : 'development';
|
||||
const isProdBuild = NODE_ENV === 'production';
|
||||
const isQuickBuild = QUICK_BUILD === 'true';
|
||||
@ -108,7 +104,7 @@ module.exports = (env, argv, { SRC_DIR, ENTRY }) => {
|
||||
exclude: /node_modules/,
|
||||
loader: 'babel-loader',
|
||||
options: {
|
||||
plugins: ['react-refresh/babel'],
|
||||
plugins: isProdBuild ? [] : ['react-refresh/babel'],
|
||||
},
|
||||
},
|
||||
]),
|
||||
|
||||
@ -46,8 +46,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"@cornerstonejs/adapters": "^2.2.4",
|
||||
"@cornerstonejs/core": "^2.2.4",
|
||||
"@cornerstonejs/adapters": "^2.2.20",
|
||||
"@cornerstonejs/core": "^2.2.20",
|
||||
"@kitware/vtk.js": "32.1.0",
|
||||
"react-color": "^2.19.3"
|
||||
}
|
||||
|
||||
@ -46,8 +46,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"@cornerstonejs/adapters": "^2.2.4",
|
||||
"@cornerstonejs/core": "^2.2.4",
|
||||
"@cornerstonejs/adapters": "^2.2.20",
|
||||
"@cornerstonejs/core": "^2.2.20",
|
||||
"@kitware/vtk.js": "32.1.0",
|
||||
"react-color": "^2.19.3"
|
||||
}
|
||||
|
||||
@ -46,9 +46,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"@cornerstonejs/adapters": "^2.2.4",
|
||||
"@cornerstonejs/core": "^2.2.4",
|
||||
"@cornerstonejs/tools": "^2.2.4",
|
||||
"@cornerstonejs/adapters": "^2.2.20",
|
||||
"@cornerstonejs/core": "^2.2.20",
|
||||
"@cornerstonejs/tools": "^2.2.20",
|
||||
"classnames": "^2.3.2"
|
||||
}
|
||||
}
|
||||
|
||||
@ -42,8 +42,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"@cornerstonejs/core": "^2.2.4",
|
||||
"@cornerstonejs/tools": "^2.2.4",
|
||||
"@cornerstonejs/core": "^2.2.20",
|
||||
"@cornerstonejs/tools": "^2.2.20",
|
||||
"classnames": "^2.3.2"
|
||||
}
|
||||
}
|
||||
|
||||
@ -38,7 +38,7 @@
|
||||
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
|
||||
"@cornerstonejs/codec-openjpeg": "^1.2.4",
|
||||
"@cornerstonejs/codec-openjph": "^2.4.5",
|
||||
"@cornerstonejs/dicom-image-loader": "^2.2.4",
|
||||
"@cornerstonejs/dicom-image-loader": "^2.2.20",
|
||||
"@icr/polyseg-wasm": "^0.4.0",
|
||||
"@ohif/core": "3.9.1",
|
||||
"@ohif/ui": "3.9.1",
|
||||
@ -55,9 +55,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"@cornerstonejs/adapters": "^2.2.4",
|
||||
"@cornerstonejs/core": "^2.2.4",
|
||||
"@cornerstonejs/tools": "^2.2.4",
|
||||
"@cornerstonejs/adapters": "^2.2.20",
|
||||
"@cornerstonejs/core": "^2.2.20",
|
||||
"@cornerstonejs/tools": "^2.2.20",
|
||||
"@icr/polyseg-wasm": "^0.4.0",
|
||||
"@kitware/vtk.js": "32.1.0",
|
||||
"html2canvas": "^1.4.1",
|
||||
|
||||
@ -45,7 +45,7 @@ import {
|
||||
useSegmentationPresentationStore,
|
||||
useSynchronizersStore,
|
||||
} from './stores';
|
||||
import { useToggleOneUpViewportGridStore } from '../../default/src/stores/useToggleOneUpViewportGridStore';
|
||||
import { useToggleOneUpViewportGridStore } from '@ohif/extension-default';
|
||||
import { useActiveViewportSegmentationRepresentations } from './hooks/useActiveViewportSegmentationRepresentations';
|
||||
import { useMeasurements } from './hooks/useMeasurements';
|
||||
import getPanelModule from './getPanelModule';
|
||||
|
||||
@ -38,6 +38,7 @@ import { SegmentationRepresentations } from '@cornerstonejs/tools/enums';
|
||||
import { useLutPresentationStore } from './stores/useLutPresentationStore';
|
||||
import { usePositionPresentationStore } from './stores/usePositionPresentationStore';
|
||||
import { useSegmentationPresentationStore } from './stores/useSegmentationPresentationStore';
|
||||
import { imageRetrieveMetadataProvider } from '@cornerstonejs/core/utilities';
|
||||
|
||||
const { registerColormap } = csUtilities.colormap;
|
||||
|
||||
@ -135,9 +136,21 @@ export default async function init({
|
||||
cornerstoneStreamingDynamicImageVolumeLoader
|
||||
);
|
||||
|
||||
hangingProtocolService.registerImageLoadStrategy('interleaveCenter', interleaveCenterLoader);
|
||||
hangingProtocolService.registerImageLoadStrategy('interleaveTopToBottom', interleaveTopToBottom);
|
||||
hangingProtocolService.registerImageLoadStrategy('nth', nthLoader);
|
||||
// Register strategies using the wrapper
|
||||
const imageLoadStrategies = {
|
||||
interleaveCenter: interleaveCenterLoader,
|
||||
interleaveTopToBottom: interleaveTopToBottom,
|
||||
nth: nthLoader,
|
||||
};
|
||||
|
||||
Object.entries(imageLoadStrategies).forEach(([name, strategyFn]) => {
|
||||
hangingProtocolService.registerImageLoadStrategy(
|
||||
name,
|
||||
createMetadataWrappedStrategy(strategyFn)
|
||||
);
|
||||
});
|
||||
|
||||
// ... existing code ...
|
||||
|
||||
// add metadata providers
|
||||
metaData.addProvider(
|
||||
@ -296,6 +309,28 @@ function initializeWebWorkerProgressHandler(uiNotificationService) {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a wrapped image load strategy with metadata handling
|
||||
* @param strategyFn - The image loading strategy function to wrap
|
||||
* @returns A wrapped strategy function that handles metadata configuration
|
||||
*/
|
||||
const createMetadataWrappedStrategy = (strategyFn: (args: any) => any) => {
|
||||
return (args: any) => {
|
||||
const clonedConfig = imageRetrieveMetadataProvider.clone();
|
||||
imageRetrieveMetadataProvider.clear();
|
||||
|
||||
try {
|
||||
const result = strategyFn(args);
|
||||
return result;
|
||||
} finally {
|
||||
// Ensure metadata is always restored, even if there's an error
|
||||
setTimeout(() => {
|
||||
imageRetrieveMetadataProvider.restore(clonedConfig);
|
||||
}, 10);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
function CPUModal() {
|
||||
return (
|
||||
<div>
|
||||
|
||||
@ -59,10 +59,10 @@ const initMeasurementService = (
|
||||
'Crosshairs',
|
||||
Length.matchingCriteria,
|
||||
() => {
|
||||
console.warn('Crosshairs mapping not implemented.');
|
||||
return null;
|
||||
},
|
||||
() => {
|
||||
console.warn('Crosshairs mapping not implemented.');
|
||||
return null;
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@ -1043,6 +1043,11 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
|
||||
// Store the current position presentations for each viewport.
|
||||
viewports.forEach(({ id: viewportId }) => {
|
||||
const presentation = this._getPositionPresentation(viewportId);
|
||||
|
||||
// During a resize, the slice index should remain unchanged. This is a temporary fix for
|
||||
// a larger issue regarding the definition of slice index with slab thickness.
|
||||
// We need to revisit this to make it more robust and understandable.
|
||||
delete presentation.viewReference.sliceIndex;
|
||||
this.beforeResizePositionPresentations.set(viewportId, presentation);
|
||||
});
|
||||
|
||||
@ -1051,10 +1056,12 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
|
||||
renderingEngine.resize(isImmediate);
|
||||
renderingEngine.render();
|
||||
|
||||
// Reset the camera for viewports that should reset their camera on resize,
|
||||
// Reset the camera for all viewports using position presentation to maintain relative size/position
|
||||
// which means only those viewports that have a zoom level of 1.
|
||||
this.beforeResizePositionPresentations.forEach((positionPresentation, viewportId) => {
|
||||
this.setPresentations(viewportId, { positionPresentation });
|
||||
this.setPresentations(viewportId, {
|
||||
positionPresentation,
|
||||
});
|
||||
});
|
||||
|
||||
// Resize and render the rendering engine again.
|
||||
|
||||
@ -108,7 +108,7 @@ export default function interleaveTopToBottom({
|
||||
volumes.forEach(volume => {
|
||||
const requests = volume.getImageLoadRequests();
|
||||
|
||||
if (!requests.length || !requests[0] || !requests[0].imageId) {
|
||||
if (!requests?.[0]?.imageId) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -93,7 +93,7 @@ function createDicomJSONApi(dicomJsonConfig) {
|
||||
|
||||
const { query } = qs.parseUrl(instance.url);
|
||||
|
||||
// Add imageId specific mapping to this data as the URL isn't necessarliy WADO-URI.
|
||||
// Add imageId specific mapping to this data as the URL isn't necessarily WADO-URI.
|
||||
metadataProvider.addImageIdToUIDs(imageId, {
|
||||
StudyInstanceUID,
|
||||
SeriesInstanceUID,
|
||||
|
||||
@ -142,9 +142,7 @@ function createDicomLocalApi(dicomLocalConfig) {
|
||||
study.series.forEach(aSeries => {
|
||||
const { SeriesInstanceUID } = aSeries;
|
||||
|
||||
const isMultiframe = aSeries.instances[0].NumberOfFrames > 1;
|
||||
|
||||
aSeries.instances.forEach((instance, index) => {
|
||||
aSeries.instances.forEach(instance => {
|
||||
const {
|
||||
url: imageId,
|
||||
StudyInstanceUID,
|
||||
@ -153,14 +151,22 @@ function createDicomLocalApi(dicomLocalConfig) {
|
||||
} = instance;
|
||||
|
||||
instance.imageId = imageId;
|
||||
|
||||
// Add imageId specific mapping to this data as the URL isn't necessarily WADO-URI.
|
||||
metadataProvider.addImageIdToUIDs(imageId, {
|
||||
StudyInstanceUID,
|
||||
SeriesInstanceUID,
|
||||
SOPInstanceUID,
|
||||
frameIndex: isMultiframe ? index : 1,
|
||||
});
|
||||
const numberOfFrames = instance.NumberOfFrames || 1;
|
||||
// Process all frames consistently, whether single or multiframe
|
||||
for (let i = 0; i < numberOfFrames; i++) {
|
||||
const frameNumber = i + 1;
|
||||
const frameImageId = implementation.getImageIdsForInstance({
|
||||
instance,
|
||||
frame: frameNumber,
|
||||
});
|
||||
// Add imageId specific mapping to this data as the URL isn't necessarily WADO-URI.
|
||||
metadataProvider.addImageIdToUIDs(frameImageId, {
|
||||
StudyInstanceUID,
|
||||
SeriesInstanceUID,
|
||||
SOPInstanceUID,
|
||||
frameNumber: numberOfFrames > 1 ? frameNumber : undefined,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
DicomMetadataStore._broadcastEvent(EVENTS.INSTANCES_ADDED, {
|
||||
@ -209,9 +215,11 @@ function createDicomLocalApi(dicomLocalConfig) {
|
||||
return imageIds;
|
||||
},
|
||||
getImageIdsForInstance({ instance, frame }) {
|
||||
if (instance.imageId) {
|
||||
return instance.imageId;
|
||||
}
|
||||
// Important: Never use instance.imageId because it might be multiframe,
|
||||
// which would make it an invalid imageId.
|
||||
// if (instance.imageId) {
|
||||
// return instance.imageId;
|
||||
// }
|
||||
|
||||
const { StudyInstanceUID, SeriesInstanceUID, SOPInstanceUID } = instance;
|
||||
const storedInstance = DicomMetadataStore.getInstance(
|
||||
|
||||
@ -434,23 +434,32 @@ function createDicomWebApi(dicomWebConfig, servicesManager) {
|
||||
instance.wadoRoot = dicomWebConfig.wadoRoot;
|
||||
instance.wadoUri = dicomWebConfig.wadoUri;
|
||||
|
||||
const imageId = implementation.getImageIdsForInstance({
|
||||
instance,
|
||||
});
|
||||
const { StudyInstanceUID, SeriesInstanceUID, SOPInstanceUID } = instance;
|
||||
|
||||
const numberOfFrames = instance.NumberOfFrames || 1;
|
||||
// Process all frames consistently, whether single or multiframe
|
||||
for (let i = 0; i < numberOfFrames; i++) {
|
||||
const frameNumber = i + 1;
|
||||
const frameImageId = implementation.getImageIdsForInstance({
|
||||
instance,
|
||||
frame: frameNumber,
|
||||
});
|
||||
// Add imageId specific mapping to this data as the URL isn't necessarily WADO-URI.
|
||||
metadataProvider.addImageIdToUIDs(frameImageId, {
|
||||
StudyInstanceUID,
|
||||
SeriesInstanceUID,
|
||||
SOPInstanceUID,
|
||||
frameNumber: numberOfFrames > 1 ? frameNumber : undefined,
|
||||
});
|
||||
}
|
||||
|
||||
// Adding imageId to each instance
|
||||
// Todo: This is not the best way I can think of to let external
|
||||
// metadata handlers know about the imageId that is stored in the store
|
||||
instance.imageId = imageId;
|
||||
|
||||
// Adding UIDs to metadataProvider
|
||||
// Note: storing imageURI in metadataProvider since stack viewports
|
||||
// will use the same imageURI
|
||||
metadataProvider.addImageIdToUIDs(imageId, {
|
||||
StudyInstanceUID,
|
||||
SeriesInstanceUID: instance.SeriesInstanceUID,
|
||||
SOPInstanceUID: instance.SOPInstanceUID,
|
||||
const imageId = implementation.getImageIdsForInstance({
|
||||
instance,
|
||||
});
|
||||
instance.imageId = imageId;
|
||||
});
|
||||
|
||||
DicomMetadataStore.addInstances(naturalizedInstances, madeInClient);
|
||||
|
||||
@ -32,8 +32,8 @@
|
||||
"start": "yarn run dev"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@cornerstonejs/core": "^2.2.4",
|
||||
"@cornerstonejs/tools": "^2.2.4",
|
||||
"@cornerstonejs/core": "^2.2.20",
|
||||
"@cornerstonejs/tools": "^2.2.20",
|
||||
"@ohif/core": "3.9.1",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.9.1",
|
||||
"@ohif/extension-default": "3.9.1",
|
||||
|
||||
@ -9,6 +9,7 @@ import { StudyBrowser } from '@ohif/ui-next';
|
||||
import { useTrackedMeasurements } from '../../getContextModule';
|
||||
import { Separator } from '@ohif/ui-next';
|
||||
import { PanelStudyBrowserHeader } from '@ohif/extension-default';
|
||||
import { useAppConfig } from '@state';
|
||||
import { defaultActionIcons, defaultViewPresets } from './constants';
|
||||
|
||||
const { formatDate, createStudyBrowserTabs } = utils;
|
||||
@ -27,7 +28,7 @@ const thumbnailNoImageModalities = [
|
||||
*
|
||||
* @param {*} param0
|
||||
*/
|
||||
function PanelStudyBrowserTracking({
|
||||
export default function PanelStudyBrowserTracking({
|
||||
servicesManager,
|
||||
getImageSrc,
|
||||
getStudiesForPatientByMRN,
|
||||
@ -45,6 +46,10 @@ function PanelStudyBrowserTracking({
|
||||
customizationService,
|
||||
} = servicesManager.services;
|
||||
const navigate = useNavigate();
|
||||
const { mode: studyMode } = customizationService.getCustomization('PanelStudyBrowser.studyMode', {
|
||||
id: 'default',
|
||||
mode: 'all',
|
||||
});
|
||||
|
||||
const { t } = useTranslation('Common');
|
||||
|
||||
@ -55,7 +60,8 @@ function PanelStudyBrowserTracking({
|
||||
const [{ activeViewportId, viewports, isHangingProtocolLayout }, viewportGridService] =
|
||||
useViewportGrid();
|
||||
const [trackedMeasurements, sendTrackedMeasurementsEvent] = useTrackedMeasurements();
|
||||
const [activeTabName, setActiveTabName] = useState('all');
|
||||
|
||||
const [activeTabName, setActiveTabName] = useState(studyMode);
|
||||
const [expandedStudyInstanceUIDs, setExpandedStudyInstanceUIDs] = useState([
|
||||
...StudyInstanceUIDs,
|
||||
]);
|
||||
@ -117,6 +123,10 @@ function PanelStudyBrowserTracking({
|
||||
|
||||
const { trackedSeries } = trackedMeasurements.context;
|
||||
|
||||
useEffect(() => {
|
||||
setActiveTabName(studyMode);
|
||||
}, [studyMode]);
|
||||
|
||||
// ~~ studyDisplayList
|
||||
useEffect(() => {
|
||||
// Fetch all studies for the patient in each primary study
|
||||
@ -528,8 +538,6 @@ PanelStudyBrowserTracking.propTypes = {
|
||||
requestDisplaySetCreationForStudy: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default PanelStudyBrowserTracking;
|
||||
|
||||
function getImageIdForThumbnail(displaySet: any, imageIds: any) {
|
||||
let imageId;
|
||||
if (displaySet.isDynamicVolume) {
|
||||
|
||||
@ -6,6 +6,11 @@ export const performCustomizations = customizationService => {
|
||||
id: 'PanelSegmentation.disableEditing',
|
||||
disableEditing: true,
|
||||
},
|
||||
// to only show current study in the panel study browser
|
||||
// {
|
||||
// id: 'PanelStudyBrowser.studyMode',
|
||||
// mode: 'primary',
|
||||
// },
|
||||
// To disable editing in the MeasurementTable
|
||||
// {
|
||||
// id: 'PanelMeasurement.disableEditing',
|
||||
|
||||
@ -84,7 +84,7 @@ function modeFactory({ modeConfiguration }) {
|
||||
lesionStats: 'Lesion Statistics',
|
||||
minValue: 'Minimum Value',
|
||||
maxValue: 'Maximum Value',
|
||||
meanValue: 'Mean Value',
|
||||
meanValue: 'Mean Value (ml)',
|
||||
volume: 'Volume',
|
||||
suvPeak: 'SUV Peak',
|
||||
suvMax: 'Maximum SUV',
|
||||
|
||||
@ -120,7 +120,7 @@ function modeFactory({ modeConfiguration }) {
|
||||
minValue: 'Minimum Value',
|
||||
maxValue: 'Maximum Value',
|
||||
meanValue: 'Mean Value',
|
||||
volume: 'Volume',
|
||||
volume: 'Volume (ml)',
|
||||
suvPeak: 'SUV Peak',
|
||||
suvMax: 'Maximum SUV',
|
||||
suvMaxIJK: 'SUV Max IJK',
|
||||
|
||||
@ -221,8 +221,6 @@ http {
|
||||
|
||||
location / {
|
||||
add_header Cache-Control "no-store, no-cache, must-revalidate";
|
||||
add_header 'Cross-Origin-Opener-Policy' 'same-origin' always;
|
||||
add_header 'Cross-Origin-Embedder-Policy' 'require-corp' always;
|
||||
}
|
||||
|
||||
location /keycloak/ {
|
||||
|
||||
@ -79,8 +79,6 @@ http {
|
||||
index index.html;
|
||||
try_files $uri $uri/ /index.html;
|
||||
add_header Cache-Control "no-store, no-cache, must-revalidate";
|
||||
add_header Cross-Origin-Opener-Policy 'same-origin' always;
|
||||
add_header Cross-Origin-Embedder-Policy 'require-corp' always;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -191,8 +191,6 @@ http {
|
||||
|
||||
location / {
|
||||
add_header Cache-Control "no-store, no-cache, must-revalidate";
|
||||
add_header 'Cross-Origin-Opener-Policy' 'same-origin' always;
|
||||
add_header 'Cross-Origin-Embedder-Policy' 'require-corp' always;
|
||||
}
|
||||
|
||||
location /keycloak/ {
|
||||
|
||||
@ -78,8 +78,6 @@ http {
|
||||
index index.html;
|
||||
try_files $uri $uri/ /index.html;
|
||||
add_header Cache-Control "no-store, no-cache, must-revalidate";
|
||||
add_header 'Cross-Origin-Opener-Policy' 'same-origin' always;
|
||||
add_header 'Cross-Origin-Embedder-Policy' 'require-corp' always;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -182,8 +182,6 @@ http {
|
||||
index index.html;
|
||||
try_files $uri $uri/ /index.html;
|
||||
add_header Cache-Control "no-store, no-cache, must-revalidate";
|
||||
add_header 'Cross-Origin-Opener-Policy' 'same-origin' always;
|
||||
add_header 'Cross-Origin-Embedder-Policy' 'require-corp' always;
|
||||
}
|
||||
|
||||
# EXAMPLE: Reverse Proxy, no auth
|
||||
|
||||
@ -118,8 +118,6 @@ http {
|
||||
index index.html;
|
||||
try_files $uri $uri/ /index.html;
|
||||
add_header Cache-Control "no-store, no-cache, must-revalidate";
|
||||
add_header 'Cross-Origin-Opener-Policy' 'same-origin' always;
|
||||
add_header 'Cross-Origin-Embedder-Policy' 'require-corp' always;
|
||||
}
|
||||
|
||||
# EXAMPLE: Redirect server error pages to the static page /40x.html
|
||||
|
||||
@ -133,8 +133,6 @@ module.exports = (env, argv) => {
|
||||
new InjectManifest({
|
||||
swDest: 'sw.js',
|
||||
swSrc: path.join(SRC_DIR, 'service-worker.js'),
|
||||
// Increase the limit to 4mb:
|
||||
maximumFileSizeToCacheInBytes: 5 * 1024 * 1024,
|
||||
// Need to exclude the theme as it is updated independently
|
||||
exclude: [/theme/],
|
||||
// Cache large files for the manifests to avoid warning messages
|
||||
@ -174,10 +172,6 @@ module.exports = (env, argv) => {
|
||||
disableDotRule: true,
|
||||
index: PUBLIC_URL + 'index.html',
|
||||
},
|
||||
headers: {
|
||||
'Cross-Origin-Embedder-Policy': 'require-corp',
|
||||
'Cross-Origin-Opener-Policy': 'same-origin',
|
||||
},
|
||||
devMiddleware: {
|
||||
writeToDisk: true,
|
||||
},
|
||||
@ -206,5 +200,9 @@ module.exports = (env, argv) => {
|
||||
);
|
||||
}
|
||||
|
||||
mergedConfig.watchOptions = {
|
||||
ignored: /node_modules\/@cornerstonejs/,
|
||||
};
|
||||
|
||||
return mergedConfig;
|
||||
};
|
||||
|
||||
@ -73,7 +73,10 @@ function getRuntimeLoadModesExtensions(modules) {
|
||||
dynamicLoad.push(
|
||||
` if( module==="${packageName}") {`,
|
||||
` const imported = await window.browserImportFunction('${module.importPath}');`,
|
||||
' return ' + (module.globalName ? `window["${module.globalName}"];` : `imported["${module.importName || 'default'}"];`),
|
||||
' return ' +
|
||||
(module.globalName
|
||||
? `window["${module.globalName}"];`
|
||||
: `imported["${module.importName || 'default'}"];`),
|
||||
' }'
|
||||
);
|
||||
return;
|
||||
@ -201,12 +204,6 @@ function writePluginImportsFile(SRC_DIR, DIST_DIR) {
|
||||
'dist'
|
||||
);
|
||||
|
||||
console.warn('copy plugins', [
|
||||
...copyPluginPublicToDistBuild,
|
||||
...copyPluginPublicToDistLink,
|
||||
...copyPluginDistToDistBuild,
|
||||
...copyPluginDistToDistLink,
|
||||
]);
|
||||
return [
|
||||
...copyPluginPublicToDistBuild,
|
||||
...copyPluginPublicToDistLink,
|
||||
|
||||
@ -53,7 +53,7 @@
|
||||
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
|
||||
"@cornerstonejs/codec-openjpeg": "^1.2.4",
|
||||
"@cornerstonejs/codec-openjph": "^2.4.5",
|
||||
"@cornerstonejs/dicom-image-loader": "^2.2.4",
|
||||
"@cornerstonejs/dicom-image-loader": "^2.2.20",
|
||||
"@emotion/serialize": "^1.1.3",
|
||||
"@ohif/core": "3.9.1",
|
||||
"@ohif/extension-cornerstone": "3.9.1",
|
||||
|
||||
@ -1,12 +1,3 @@
|
||||
{
|
||||
"rewrites": [{ "source": "*", "destination": "index.html" }],
|
||||
"headers": [
|
||||
{
|
||||
"source": "**/*",
|
||||
"headers": [
|
||||
{ "key": "Cross-Origin-Embedder-Policy", "value": "require-corp" },
|
||||
{ "key": "Cross-Origin-Opener-Policy", "value": "same-origin" }
|
||||
]
|
||||
}
|
||||
]
|
||||
"rewrites": [{ "source": "*", "destination": "index.html" }]
|
||||
}
|
||||
|
||||
@ -2,7 +2,3 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
* {
|
||||
min-height: 0 !important;
|
||||
}
|
||||
|
||||
@ -37,7 +37,7 @@
|
||||
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
|
||||
"@cornerstonejs/codec-openjpeg": "^1.2.4",
|
||||
"@cornerstonejs/codec-openjph": "^2.4.5",
|
||||
"@cornerstonejs/dicom-image-loader": "^2.2.4",
|
||||
"@cornerstonejs/dicom-image-loader": "^2.2.20",
|
||||
"@ohif/ui": "3.9.1",
|
||||
"cornerstone-math": "0.1.9",
|
||||
"dicom-parser": "^1.8.21"
|
||||
|
||||
@ -8,7 +8,6 @@ import toNumber from '../utils/toNumber';
|
||||
import combineFrameInstance from '../utils/combineFrameInstance';
|
||||
|
||||
class MetadataProvider {
|
||||
private readonly studies: Map<string, any> = new Map();
|
||||
private readonly imageURIToUIDs: Map<string, any> = new Map();
|
||||
private readonly imageUIDsByImageId: Map<string, any> = new Map();
|
||||
// Can be used to store custom metadata for a specific type.
|
||||
@ -17,6 +16,10 @@ class MetadataProvider {
|
||||
private readonly customMetadata: Map<string, any> = new Map();
|
||||
|
||||
addImageIdToUIDs(imageId, uids) {
|
||||
if (!imageId) {
|
||||
throw new Error('MetadataProvider::Empty imageId');
|
||||
}
|
||||
|
||||
// This method is a fallback for when you don't have WADO-URI or WADO-RS.
|
||||
// You can add instances fetched by any method by calling addInstance, and hook an imageId to point at it here.
|
||||
// An example would be dicom hosted at some random site.
|
||||
@ -35,6 +38,10 @@ class MetadataProvider {
|
||||
}
|
||||
|
||||
_getInstance(imageId) {
|
||||
if (!imageId) {
|
||||
throw new Error('MetadataProvider::Empty imageId');
|
||||
}
|
||||
|
||||
const uids = this.getUIDsFromImageID(imageId);
|
||||
|
||||
if (!uids) {
|
||||
@ -455,17 +462,6 @@ class MetadataProvider {
|
||||
}
|
||||
|
||||
getUIDsFromImageID(imageId) {
|
||||
if (!imageId) {
|
||||
throw new Error('MetadataProvider::Empty imageId');
|
||||
}
|
||||
// TODO: adding csiv here is not really correct. Probably need to use
|
||||
// metadataProvider.addImageIdToUIDs(imageId, {
|
||||
// StudyInstanceUID,
|
||||
// SeriesInstanceUID,
|
||||
// SOPInstanceUID,
|
||||
// })
|
||||
// somewhere else
|
||||
|
||||
const cachedUIDs = this.imageUIDsByImageId.get(imageId);
|
||||
if (cachedUIDs) {
|
||||
return cachedUIDs;
|
||||
|
||||
@ -280,7 +280,7 @@ export default class CustomizationService extends PubSubService {
|
||||
return customization;
|
||||
}
|
||||
const parent = this.getCustomization(customizationType);
|
||||
const result = parent ? Object.assign(Object.create(parent), customization) : customization;
|
||||
const result = parent ? Object.assign({}, parent, customization) : customization;
|
||||
// Execute an nested type information
|
||||
return result.transform?.(this) || result;
|
||||
}
|
||||
|
||||
@ -679,7 +679,7 @@ class StudyPrefetcherService extends PubSubService {
|
||||
this._displaySetLoadingStates.clear();
|
||||
this._imageIdsToDisplaySetsMap.clear();
|
||||
this._inflightRequests.clear();
|
||||
this.imageLoadPoolManager.clearRequestStack(IMAGE_REQUEST_TYPE);
|
||||
this.imageLoadPoolManager.clearRequestStack(this.requestType);
|
||||
|
||||
this._broadcastEvent(this.EVENTS.SERVICE_STOPPED, {});
|
||||
}
|
||||
|
||||
@ -81,6 +81,7 @@ declare global {
|
||||
}
|
||||
|
||||
export interface Config {
|
||||
studyBrowserMode?: 'all' | 'primary';
|
||||
routerBasename?: string;
|
||||
customizationService?: CustomizationServiceType;
|
||||
extensions?: string[];
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import { vec3 } from 'gl-matrix';
|
||||
|
||||
/**
|
||||
* Combine the Per instance frame data, the shared frame data
|
||||
* and the root data objects.
|
||||
@ -9,25 +11,28 @@
|
||||
* single frame data. (eg frame is undefined is the same as frame===1).
|
||||
*/
|
||||
const combineFrameInstance = (frame, instance) => {
|
||||
const { PerFrameFunctionalGroupsSequence, SharedFunctionalGroupsSequence, NumberOfFrames } =
|
||||
instance;
|
||||
const {
|
||||
PerFrameFunctionalGroupsSequence,
|
||||
SharedFunctionalGroupsSequence,
|
||||
NumberOfFrames,
|
||||
SpacingBetweenSlices,
|
||||
} = instance;
|
||||
|
||||
if (PerFrameFunctionalGroupsSequence || NumberOfFrames > 1) {
|
||||
const frameNumber = Number.parseInt(frame || 1);
|
||||
const shared = (
|
||||
SharedFunctionalGroupsSequence ? Object.values(SharedFunctionalGroupsSequence[0]) : []
|
||||
)
|
||||
.filter(it => !!it)
|
||||
.map(it => it[0])
|
||||
.filter(it => it !== undefined && typeof it === 'object');
|
||||
const perFrame = (
|
||||
PerFrameFunctionalGroupsSequence
|
||||
? Object.values(PerFrameFunctionalGroupsSequence[frameNumber - 1])
|
||||
: []
|
||||
)
|
||||
.filter(it => !!it)
|
||||
.map(it => it[0])
|
||||
.filter(it => it !== undefined && typeof it === 'object');
|
||||
const shared = SharedFunctionalGroupsSequence
|
||||
? Object.values(SharedFunctionalGroupsSequence[0])
|
||||
.filter(Boolean)
|
||||
.map(it => it[0])
|
||||
.filter(it => typeof it === 'object')
|
||||
: [];
|
||||
|
||||
const perFrame = PerFrameFunctionalGroupsSequence
|
||||
? Object.values(PerFrameFunctionalGroupsSequence[frameNumber - 1])
|
||||
.filter(Boolean)
|
||||
.map(it => it[0])
|
||||
.filter(it => typeof it === 'object')
|
||||
: [];
|
||||
|
||||
// this is to fix NM multiframe datasets with position and orientation
|
||||
// information inside DetectorInformationSequence
|
||||
@ -35,9 +40,40 @@ const combineFrameInstance = (frame, instance) => {
|
||||
instance.ImageOrientationPatient =
|
||||
instance.DetectorInformationSequence[0].ImageOrientationPatient;
|
||||
}
|
||||
|
||||
let ImagePositionPatientToUse = instance.ImagePositionPatient;
|
||||
|
||||
if (!instance.ImagePositionPatient && instance.DetectorInformationSequence) {
|
||||
instance.ImagePositionPatient = instance.DetectorInformationSequence[0].ImagePositionPatient;
|
||||
const imagePositionPatient = instance.DetectorInformationSequence[0].ImagePositionPatient;
|
||||
const imageOrientationPatient = instance.ImageOrientationPatient;
|
||||
|
||||
// Calculate the position for the current frame
|
||||
if (imageOrientationPatient && SpacingBetweenSlices) {
|
||||
const rowOrientation = vec3.fromValues(
|
||||
imageOrientationPatient[0],
|
||||
imageOrientationPatient[1],
|
||||
imageOrientationPatient[2]
|
||||
);
|
||||
|
||||
const colOrientation = vec3.fromValues(
|
||||
imageOrientationPatient[3],
|
||||
imageOrientationPatient[4],
|
||||
imageOrientationPatient[5]
|
||||
);
|
||||
|
||||
const normalVector = vec3.cross(vec3.create(), rowOrientation, colOrientation);
|
||||
|
||||
const position = vec3.scaleAndAdd(
|
||||
vec3.create(),
|
||||
imagePositionPatient,
|
||||
normalVector,
|
||||
SpacingBetweenSlices * (frameNumber - 1)
|
||||
);
|
||||
|
||||
ImagePositionPatientToUse = [position[0], position[1], position[2]];
|
||||
}
|
||||
}
|
||||
console.debug('🚀 ~ ImagePositionPatientToUse:', ImagePositionPatientToUse);
|
||||
|
||||
const newInstance = Object.assign(instance, { frameNumber: frameNumber });
|
||||
|
||||
@ -52,7 +88,8 @@ const combineFrameInstance = (frame, instance) => {
|
||||
// back to the dicomMetaStore so we don't have to do this again.
|
||||
return {
|
||||
...newInstance,
|
||||
ImagePositionPatient: newInstance.ImagePositionPatient ?? [0, 0, frameNumber],
|
||||
ImagePositionPatient: ImagePositionPatientToUse ??
|
||||
newInstance.ImagePositionPatient ?? [0, 0, frameNumber],
|
||||
};
|
||||
} else {
|
||||
return instance;
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 142 KiB After Width: | Height: | Size: 307 KiB |
@ -102,18 +102,12 @@ directory:
|
||||
yarn global add http-server
|
||||
|
||||
# Change the directory to the platform/app
|
||||
cd platform/app
|
||||
|
||||
# Serve the files in our current directory
|
||||
npx serve ./dist -c ../public/serve.json
|
||||
```
|
||||
|
||||
:::caution
|
||||
In the video below notice that there is `platform/viewer` which has been renamed to `platform/app` in the latest version
|
||||
:::
|
||||
|
||||
<div style={{padding:"56.25% 0 0 0", position:"relative"}}>
|
||||
<iframe src="https://player.vimeo.com/video/551957266?badge=0&autopause=0&player_id=0&app_id=58479" frameBorder="0" allow="autoplay; fullscreen; picture-in-picture" allowFullScreen style= {{ position:"absolute",top:0,left:0,width:"100%",height:"100%"}} title="measurement-report"></iframe>
|
||||
</div>
|
||||
|
||||
|
||||
### Automating Builds and Deployments
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
---
|
||||
sidebar_position: 7
|
||||
sidebar_position: 8
|
||||
---
|
||||
|
||||
# Cross-Origin Information for OHIF
|
||||
@ -7,42 +7,10 @@ sidebar_position: 7
|
||||
This document describes various security configurations, settings and environments/contexts needed to fully leverage OHIF’s capabilities. One may need some configurations while others might need ALL of them - it all depends on the environment OHIF is expected to run in.
|
||||
|
||||
In particular, three of OHIF’s features depend on these configurations:
|
||||
- [OHIF’s use of SharedArrayBuffer](#sharedarraybuffer)
|
||||
- [Embedding OHIF in an iframe](#embedding-ohif-in-an-iframe)
|
||||
- [XMLHttpRequests to fetch data from data sources](#cors-in-ohif)
|
||||
|
||||
|
||||
|
||||
## SharedArrayBuffer
|
||||
A `SharedArrayBuffer` is a JavaScript object that is similar to an `ArrayBuffer` but can be shared between web workers and the window that spawned them via the `postMessage` API. See [SharedArrayBuffer in MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer) for more information.
|
||||
|
||||
:::tip
|
||||
To turn off Shared Array Buffer completely, just set `useSharedArrayBuffer` to `false` in the [OHIF configuration](../configuration/configurationFiles.md). But keep in mind that you will not get the performance boost that Shared Array Buffer offers for decoding and rendering big volumes where web workers write to the same memory space.
|
||||
:::
|
||||
|
||||
### Security Requirements
|
||||
|
||||
In order to use `SharedArrayBuffer` objects in the browser, the following security conditions must be met:
|
||||
|
||||
- The page must be served in a [secure context](#secure-context).
|
||||
- The page must have [cross-origin isolation](#cross-origin-isolation) enabled.
|
||||
|
||||
### `SharedArrayBuffer` in OHIF
|
||||
|
||||
OHIF uses `SharedArrayBuffer` in its volume loader (from Cornerstone3D). It comes with the benefit of improved performance and optimization at the cost of some configuration to use it.
|
||||
|
||||
As such, if the following popup is shown when launching OHIF then the OHIF server will have to be configured to permit the loading of volumetric images and data. Note that stack viewports are still available and functional even when this error is present.
|
||||
|
||||

|
||||
|
||||
To better determine which (if not all) of the [security requirements](#security-requirements) are lacking, have a look at the browser console.
|
||||
|
||||
Output in the console similar to the following indicates that OHIF is not running in a [secure context](#secure-context).
|
||||
|
||||

|
||||
|
||||
Absence of the above error in the console together with the presence of the Cross Origin Isolation popup warning, likely indicates that either or both of the [COOP](#coop---cross-origin-opener-policy) and/or [COEP](#coep---cross-origin-embedder-policy) headers are not set for OHIF.
|
||||
|
||||
## Embedding OHIF in an iframe
|
||||
|
||||
As described [here](./iframe.md), there are cases where OHIF will be embedded in an iframe. The following links provide more information for setting up and configuring OHIF to work in an iframe:
|
||||
@ -64,9 +32,6 @@ URLs that are NOT local must be delivered over `https://` or `wss://` (i.e. TLS)
|
||||
|
||||
A page embedded in an iframe is considered secure if it itself and every one of its embedding ancestors are delivered securely. Otherwise it is deemed insecure.
|
||||
|
||||
### Why does OHIF require a secure context?
|
||||
|
||||
Beyond all of the inherent benefits of a secure connection, OHIF requires a secure context so that it can utilize [SharedArrayBuffer](#sharedarraybuffer) objects for volume rendering.
|
||||
|
||||
### Configuring/setting up a secure context
|
||||
|
||||
@ -143,91 +108,8 @@ add_header 'Access-Control-Allow-Origin' '*' always;
|
||||
```
|
||||
:::
|
||||
|
||||
## COOP - Cross-Origin Opener Policy
|
||||
|
||||
The COOP HTTP response header restricts the global, root document of the page from being referenced and accessed by another cross-origin document that might open the page in a window. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy) for more information.
|
||||
|
||||
### Header Values Pertinent to OHIF (see [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy#syntax) for more information)
|
||||
|
||||
|Value|Description|
|
||||
|-----|-----------|
|
||||
|same-origin|Restricts the document to be referenced by openers of the same origin only.|
|
||||
|
||||
### COOP in OHIF
|
||||
|
||||
COOP is required for [SharedArrayBuffer](#sharedarraybuffer) usage in OHIF. See also [Troubleshooting Cross-origin Isolation in OHIF](#troubleshooting-cross-origin-isolation-in-ohif).
|
||||
|
||||
## COEP - Cross-Origin Embedder Policy
|
||||
|
||||
The COEP HTTP response header restricts cross-origin documents from being embedded into a document (e.g. in an iframe, video, image, etc). See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy) for more information.
|
||||
|
||||
### Header Values Pertinent to OHIF (see [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy#syntax) for more information)
|
||||
|
||||
|Value|Description|
|
||||
|-----|-----------|
|
||||
|require-corp|Permits the document to load either of the following embedded resources: <ul><li>Those from the same origin</li><li>Cross-origin resources embedded by a DOM element that has the appropriate [crossorigin attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/crossorigin) set</li><li>Cross-origin resources with the appropriate [CORP response header](#corp---cross-origin-resource-policy)</li></ul>
|
||||
|credentialless|See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy#syntax) for more information|
|
||||
|
||||
### COEP in OHIF
|
||||
|
||||
COEP is required for [SharedArrayBuffer](#sharedarraybuffer) usage in OHIF. See also [Troubleshooting Cross-origin Isolation in OHIF](#troubleshooting-cross-origin-isolation-in-ohif).
|
||||
|
||||
## Cross-origin Isolation
|
||||
|
||||
Cross-origin isolation is [enabled](https://web.dev/cross-origin-isolation-guide/#enable-cross-origin-isolation) for a web page when the following COOP and COEP headers are set.
|
||||
- [COOP](#coop---cross-origin-opener-policy) with `same-origin`
|
||||
- [COEP](#coep---cross-origin-embedder-policy) with `require-corp` or `credentialless`
|
||||
|
||||
### iframe
|
||||
|
||||
An iframe is considered to have cross-origin isolation enabled if it itself has the appropriate COOP and COEP headers set as well as every one of its embedding ancestors.
|
||||
|
||||
### Troubleshooting Cross-origin Isolation in OHIF
|
||||
|
||||
The [SharedArrayBuffer in OHIF](#sharedarraybuffer-in-ohif) section describes how to determine if there are problems with cross-origin isolation in OHIF. If it is determined that COOP and/or COEP is indeed an issue, then the COOP and COEP headers must be set for OHIF. How to accomplish this varies per server or service that is hosting OHIF. The following are just a few examples.
|
||||
|
||||
:::tip
|
||||
In the default dev environment, the following can be set in the webpack.pwa.js file…
|
||||
|
||||
```javascript
|
||||
devServer: {
|
||||
headers: {
|
||||
"Cross-Origin-Opener-Policy": "same-origin",
|
||||
"Cross-Origin-Embedder-Policy": "require-corp"
|
||||
}
|
||||
}
|
||||
```
|
||||
:::
|
||||
|
||||
:::tip
|
||||
If deploying OHIF using Netlify, the Netlify configuration [file](https://docs.netlify.com/configure-builds/file-based-configuration/) can be used to configure the headers as such…
|
||||
|
||||
```
|
||||
[[headers]]
|
||||
# Define which paths this specific [[headers]] block will cover.
|
||||
for = "/*"
|
||||
|
||||
[headers.values]
|
||||
Cross-Origin-Opener-Policy = "same-origin"
|
||||
Cross-Origin-Embedder-Policy = "require-corp"
|
||||
```
|
||||
:::
|
||||
|
||||
:::tip
|
||||
If OHIF is served behind nginx, then the headers can be set in the nginx.conf file as follows. The [template nginx configuration file](https://github.com/OHIF/Viewers/blob/master/.docker/Viewer-v3.x/default.conf.template) for creating a [OHIF Docker image](./docker.md#building-the-docker-image) has an example of this too.
|
||||
```nginx
|
||||
server {
|
||||
location / {
|
||||
add_header Cross-Origin-Opener-Policy same-origin;
|
||||
add_header Cross-Origin-Embedder-Policy require-corp;
|
||||
}
|
||||
}
|
||||
```
|
||||
:::
|
||||
|
||||
## CORP - Cross-Origin Resource Policy
|
||||
|
||||
The CORP HTTP response header indicates which origins can read and use a resource. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cross-Origin_Resource_Policy) for more information.
|
||||
|
||||
### Header Values (see [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cross-Origin_Resource_Policy#usage) for more information)
|
||||
|
||||
@ -239,12 +121,6 @@ The CORP HTTP response header indicates which origins can read and use a resourc
|
||||
|
||||
### OHIF and CORP
|
||||
|
||||
There are two scenarios where the CORP header is relevant to OHIF:
|
||||
|
||||
- [PDF from a Cross Origin DICOMweb Data Source](#pdf-from-a-cross-origin-dicomweb-data-source)
|
||||
- [OHIF as a Cross-origin Resource in an iframe](#ohif-as-a-cross-origin-resource-in-an-iframe)
|
||||
|
||||
Both these scenarios stem from the fact that OHIF has to be served with the [COEP](#coep---cross-origin-embedder-policy) header to support [SharedArrayBuffer](#sharedarraybuffer).
|
||||
|
||||
#### PDF from a Cross Origin DICOMweb Data Source
|
||||
|
||||
@ -266,48 +142,3 @@ If the dcm4chee server and the OHIF server are hosted on the same site, then the
|
||||
add_header 'Cross-Origin-Resource-Policy' 'same-site' always;
|
||||
```
|
||||
:::
|
||||
|
||||
#### OHIF as a Cross-origin Resource in an iframe
|
||||
|
||||
There are cases where [OHIF is embedded in an iframe](./iframe.md) and the embedding page is from a different origin. Again due to the [security requirements for SharedArrayBuffer](#security-requirements), [both OHIF and the embedding page](#iframe) must have the appropriate COEP header. In this scenario, OHIF is the cross-origin resource and since the `<iframe>` tag does not support the `crossorigin` attribute, OHIF must be served with the appropriate CORP header.
|
||||
|
||||
:::info
|
||||
Setting the CORP header such that OHIF can be embedded in an iframe varies per server or service hosting OHIF. What follows are just a few examples. Note that whenever the embedding page is hosted on the same site as OHIF, consider using the `same-site` value instead of `cross-origin`.
|
||||
:::
|
||||
|
||||
:::tip
|
||||
In the default dev environment, the following can be set in the webpack.pwa.js file…
|
||||
|
||||
```javascript
|
||||
devServer: {
|
||||
headers: {
|
||||
"Cross-Origin-Resource-Policy": "cross-origin",
|
||||
}
|
||||
}
|
||||
```
|
||||
:::
|
||||
|
||||
:::tip
|
||||
If deploying OHIF using Netlify, the Netlify configuration [file](https://docs.netlify.com/configure-builds/file-based-configuration/) can be used to configure the header as such…
|
||||
|
||||
```
|
||||
[[headers]]
|
||||
# Define which paths this specific [[headers]] block will cover.
|
||||
for = "/*"
|
||||
|
||||
[headers.values]
|
||||
Cross-Origin-Resource-Policy = "cross-origin"
|
||||
```
|
||||
:::
|
||||
|
||||
:::tip
|
||||
If OHIF is served behind nginx, then the header can be set in the nginx.conf file as follows.
|
||||
|
||||
```nginx
|
||||
server {
|
||||
location / {
|
||||
add_header Cross-Origin-Resource-Policy cross-origin;
|
||||
}
|
||||
}
|
||||
```
|
||||
:::
|
||||
|
||||
@ -35,22 +35,13 @@ PUBLIC_URL=/my-awesome-viewer/ APP_CONFIG=config/default.js yarn build
|
||||
```
|
||||
|
||||
We can use the `npx serve` to serve the build folder. There are two things you need to consider however,
|
||||
1. You need to change the public/serve.json file to reflect the new routerBasename in the destination (see the example below)
|
||||
1. You need to change the `public/serve.json` file to reflect the new routerBasename in the destination (see the example below)
|
||||
|
||||
|
||||
```json
|
||||
// final serve.json
|
||||
{
|
||||
"rewrites": [{ "source": "*", "destination": "my-awesome-viewer/index.html" }],
|
||||
"headers": [
|
||||
{
|
||||
"source": "**/*",
|
||||
"headers": [
|
||||
{ "key": "Cross-Origin-Embedder-Policy", "value": "require-corp" },
|
||||
{ "key": "Cross-Origin-Opener-Policy", "value": "same-origin" }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@ -18,6 +18,14 @@ The machine on which to build and run the Docker container must have:
|
||||
3. [Docker](https://docs.docker.com/get-docker/) installed.
|
||||
|
||||
## Building the Docker Image
|
||||
|
||||
:::info
|
||||
In this tutorial, we will build the Docker image for the OHIF Viewer and OHIF server as defined in the `default.js` config. If you need a custom build, you can modify the configuration file to include your data sources and then build the Docker image. For more information on data sources, see [here](../platform/extensions/modules/data-source.md).
|
||||
|
||||
Below we show how to point the Docker image to a custom configuration file.
|
||||
:::
|
||||
|
||||
|
||||
The docker image can be built from a terminal window as such:
|
||||
1. Switch to the OHIF Viewer code root directory.
|
||||
2. Issue the following Docker command. Note that what follows `-t` flag is the `{name}:{tag}` for the Docker image and is arbitrary when creating a local Docker image.
|
||||
@ -121,20 +129,8 @@ For SSL Docker deployments, the CORP header value is set [here](https://github.c
|
||||
We make no claims or guarantees regarding this section concerning security. If in doubt, enlist the help of an expert and conduct proper audits.
|
||||
:::
|
||||
|
||||
### Why SSL?
|
||||
As described [here](./cors.md), OHIF must be used in a [secure context](./cors.md#secure-context) in order to fully leverage all of OHIF's capabilities. Whenever OHIF is not running in a secure context and is navigated to using the OHIF's server IP address (e.g. `http://192.168.1.162:3000`) or domain name (e.g. `http://my.ohif.server`) then the following popup message will be displayed in OHIF
|
||||
|
||||

|
||||
|
||||
and the following message will appear in the browser console.
|
||||
|
||||

|
||||
|
||||
:::info
|
||||
The above indicate that OHIF is not running in a secure context. Among other things, this means information transferred to/from OHIF is not encrypted and certain capabilities such as 3D volume loading will NOT work. However, basic stack viewport functionality will continue to function.
|
||||
|
||||
Consideration must be given as to whether OHIF should be deployed in a secure context over SSL.
|
||||
:::
|
||||
If OHIF is not deployed over SSL, this means information transferred to/from OHIF is not encrypted. Consideration must be given as to whether OHIF should be deployed in a secure context over SSL.
|
||||
|
||||
### Specifying the SSL Port, Certificate and Private Key
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
---
|
||||
sidebar_position: 8
|
||||
sidebar_position: 7
|
||||
sidebar_label: iframe
|
||||
---
|
||||
|
||||
@ -40,7 +40,7 @@ The PUBLIC_URL tells the application where to find the static assets and the rou
|
||||
|
||||
### Try it locally
|
||||
|
||||
Download the index.html and the build (against the /ohif/ path) from [here](https://ohif-assets.s3.us-east-2.amazonaws.com/iframe-basic/Archive.zip)
|
||||
Download the index.html and the build (against the /ohif/ path) from [here](https://ohif-assets-new.s3.us-east-1.amazonaws.com/iframe-basic/Archive.zip)
|
||||
|
||||
Then run the
|
||||
|
||||
@ -53,119 +53,3 @@ npx http-server unzipped-folder
|
||||
You should be able to see
|
||||
|
||||

|
||||
|
||||
:::info
|
||||
Notice the Cross Origin Isolation Warning. It is present to indicate that OHIF cannot render volumes because the volume viewports
|
||||
use SharedArrayBuffer which is not allowed for non cross origin isolated apps. You can read more about Cross Origin Isolation here
|
||||
https://web.dev/coop-coep/ or follow the steps below to enable it.
|
||||
:::
|
||||
|
||||
### Fixing the Cross Origin Isolation Warning to enable volume rendering
|
||||
|
||||
For that we need a more sophisticated setup, since we need to add the Cross Origin Embedder Policy and Cross Origin Opener Policy headers
|
||||
to make the parent app cross origin isolated. For that we can use an Express server. (Note: you can use any other method
|
||||
to add the headers, this is just one of the methods)
|
||||
|
||||
Download files from [here](https://ohif-assets.s3.us-east-2.amazonaws.com/iframe-express/Archive.zip)
|
||||
|
||||
```js
|
||||
const express = require("express")
|
||||
const app = express()
|
||||
|
||||
app.use((req, res, next) => {
|
||||
res.setHeader("Cross-Origin-Opener-Policy", "same-origin")
|
||||
res.setHeader("Cross-Origin-Embedder-Policy", "require-corp")
|
||||
next()
|
||||
})
|
||||
|
||||
app.use(express.static("public")) // 'public' should be the folder with the static OHIF build files
|
||||
|
||||
app.listen(8080, () => console.log("Listening on port 8080!"))
|
||||
```
|
||||
|
||||

|
||||
|
||||
|
||||
:::tip
|
||||
if you are using webpack with react you can set
|
||||
|
||||
```js
|
||||
devServer: {
|
||||
headers: {
|
||||
"Cross-Origin-Opener-Policy": "same-origin",
|
||||
"Cross-Origin-Embedder-Policy": "require-corp"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
:::tip
|
||||
If you are using Angular, you should modify the `angular.json` file to add the headers
|
||||
|
||||
```js
|
||||
"serve": {
|
||||
//
|
||||
"configurations": {
|
||||
//
|
||||
"development": {
|
||||
//
|
||||
"headers": {
|
||||
"Cross-Origin-Opener-Policy": "same-origin",
|
||||
"Cross-Origin-Embedder-Policy": "require-corp"
|
||||
}
|
||||
}
|
||||
},
|
||||
//
|
||||
},
|
||||
```
|
||||
:::
|
||||
|
||||
|
||||
|
||||
## Development Server
|
||||
|
||||
If you are not using the static build, you can use the iframe to load the viewer from the local development server. For example, if you are running the viewer locally on port 3000, you can use the following iframe element to load the viewer:
|
||||
|
||||
```html
|
||||
// e.g., app running on 3001 and iframe loading the viewer from 3000
|
||||
<iframe src="http://localhost:3000" style="width: 100%; height: 500px; border: none"/>
|
||||
```
|
||||
|
||||
Notice that not including the static build removes the need for
|
||||
the PUBLIC_URL and the routerBasename. However, the Cross Origin Resource Policy (CORP)
|
||||
headers must be set because the viewer will be loaded from a different port. You can read
|
||||
more about CORP [here](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cross-Origin_Resource_Policy).
|
||||
Basically in the development server that is serving the viewer, add the following headers:
|
||||
|
||||
```js
|
||||
// use this if the embedding app is running on the same site as OHIF
|
||||
// (e.g. parent/embedding app is http://localhost:3001 and OHIF is http://localhost:3000)
|
||||
"Cross-Origin-Resource-Policy": "same-site"
|
||||
or
|
||||
|
||||
// use this if the embedding app is a completely different origin than OHIF (e.g.
|
||||
// parent/embedding app is http://192.168.1.2 and OHIF is http://localhost:3000)
|
||||
"Cross-Origin-Resource-Policy": "cross-origin"
|
||||
```
|
||||
|
||||
:::info
|
||||
You can't set the `Cross-Origin-Resource-Policy` to `same-origin` since the viewer is loaded from a different port.
|
||||
:::
|
||||
|
||||
:::tip
|
||||
If you are using webpack to serve the viewer it would be
|
||||
|
||||
```js
|
||||
devServer: {
|
||||
headers: {
|
||||
"Cross-Origin-Resource-Policy": "same-site" // cross-origin is also valid
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
:::tip
|
||||
Take a look at how other people have integrated OHIF in their react app
|
||||
|
||||
example1: https://github.com/OHIF/Viewers/issues/3371#issuecomment-1630405255
|
||||
:::
|
||||
|
||||
@ -35,61 +35,6 @@ package outside of the monorepo is most common with extension development. Let's
|
||||
demonstrate how to accomplish this with two commonly forked extension
|
||||
dependencies:
|
||||
|
||||
### `cornerstone-tools`
|
||||
|
||||
On your local file system:
|
||||
|
||||
```bash title="/my-projects/"
|
||||
├── cornerstonejs/cornerstone-tools
|
||||
└── ohif/viewers
|
||||
```
|
||||
|
||||
- Open a terminal/shell
|
||||
- Navigate to `cornerstonejs/cornerstone-tools`
|
||||
- `yarn install`
|
||||
- [`yarn link`](https://yarnpkg.com/en/docs/cli/link)
|
||||
- `yarn run dev`
|
||||
|
||||
* Open a new terminal/shell
|
||||
* Navigate to `ohif/viewers` (the root of ohif project)
|
||||
- `yarn install`
|
||||
- [`yarn link cornerstone-tools`](https://yarnpkg.com/en/docs/cli/link)
|
||||
- `yarn run dev`
|
||||
|
||||
As you make changed to `cornerstone-tools`, and it's output is rebuilt, you
|
||||
should see the following behavior:
|
||||
|
||||

|
||||
|
||||
If you wish to stop using your local package, run the following commands in the
|
||||
`ohif/viewers` repository root:
|
||||
|
||||
- `yarn unlink cornerstone-tools`
|
||||
- `yarn install --force`
|
||||
|
||||
<!--
|
||||
### `react-vtkjs-viewport`
|
||||
|
||||
On your local file system:
|
||||
|
||||
```bash
|
||||
# code/my-projects/
|
||||
.
|
||||
├── ohif/react-vtkjs-viewport
|
||||
└── ohif/viewers
|
||||
```
|
||||
|
||||
- Open a terminal/shell
|
||||
- Navigate to `ohif/react-vtkjs-viewport`
|
||||
- `yarn install`
|
||||
- [`yarn link`](https://yarnpkg.com/en/docs/cli/link)
|
||||
- `yarn run start`
|
||||
- Open a new terminal/shell
|
||||
- Navigate to `ohif/viewers`.
|
||||
- `yarn install`
|
||||
- [`yarn link react-vtkjs-viewport`](https://yarnpkg.com/en/docs/cli/link)
|
||||
- `yarn run dev` -->
|
||||
|
||||
#### Other linkage notes
|
||||
|
||||
We're still working out some of the kinks with local package development as
|
||||
|
||||
@ -8,55 +8,4 @@ sidebar_label: Local Linking
|
||||
Local linking allows you to develop and test a library in the context of an application before it's published or when you encounter
|
||||
a bug that you suspect is related to a library. With Yarn, this can be achieved through the yarn link command.
|
||||
|
||||
The general procedure is as follows:
|
||||
|
||||
|
||||
Link the Library:
|
||||
|
||||
```sh
|
||||
cd /path/to/library
|
||||
yarn link
|
||||
```
|
||||
|
||||
This command will create a symlink in a global directory for the library.
|
||||
|
||||
|
||||
Link to the Application:
|
||||
|
||||
```sh
|
||||
cd /path/to/application
|
||||
yarn link "library-name"
|
||||
```
|
||||
|
||||
Creates a symlink from the global directory to the application's node_modules.
|
||||
|
||||
|
||||
# Tutorial for linking Cornerstone3D to OHIF
|
||||
|
||||
Below we demonstrate how to link Cornerstone3D to OHIF Viewer. This is useful for testing and debugging Cornerstone3D in the context of OHIF Viewer.
|
||||
|
||||
<div style={{padding:"56.25% 0 0 0", position:"relative"}}>
|
||||
<iframe src="https://player.vimeo.com/video/849096279?badge=0&autopause=0&player_id=0&app_id=58479" frameBorder="0" allow="autoplay; fullscreen; picture-in-picture" allowFullScreen style= {{ position:"absolute",top:0,left:0,width:"100%",height:"100%"}} title="measurement-report"></iframe>
|
||||
</div>
|
||||
|
||||
::tip
|
||||
Since `@cornerstonejs/tools` depends on `@cornerstonejs/core`, if you need the changes
|
||||
you made in `@cornerstonejs/core` to be reflected in `@cornerstonejs/tools`, you need to
|
||||
also link `@cornerstonejs/core` to `@cornerstonejs/tools`.
|
||||
|
||||
```sh
|
||||
cd /path/to/cornerstonejs-core
|
||||
# for the core
|
||||
yarn link
|
||||
|
||||
cd /path/to/cornerstonejs-tools
|
||||
yarn link "@cornerstonejs/core"
|
||||
|
||||
# for the tools
|
||||
yarn link
|
||||
|
||||
# inside OHIF
|
||||
cd /path/to/OHIFViewer
|
||||
yarn link "@cornerstonejs/core"
|
||||
yarn link "@cornerstonejs/tools"
|
||||
```
|
||||
You can take a look at the Cornerstonejs tutorial for linking https://www.cornerstonejs.org/docs/contribute/linking
|
||||
|
||||
@ -2,14 +2,6 @@
|
||||
|
||||
|
||||
|
||||
## Why do I keep seeing a Cross Origin Isolation warning
|
||||
If you encounter a warning while running OHIF indicating that your application is not cross-origin isolated, it implies that volume rendering, such as MPR, will not function properly since they depend on Shared Array Buffers. To resolve this issue, we recommend referring to our comprehensive guide on Cross Origin Isolation available at [our dedicated cors page](../deployment/cors.md).
|
||||
|
||||
## What if my setup does not support the Shared Array Buffers API?
|
||||
You can simply disable that by adding the `useSharedArrayBuffer: 'FALSE'` (notice the string FALSE), and the volumes will only use a regular
|
||||
array buffer which is a bit slower but will work on all browsers.
|
||||
|
||||
|
||||
## Viewer opens but does not show any thumbnails
|
||||
|
||||
Thumbnails may not appear in your DICOMWeb application for various reasons. This guide focuses on one primary scenario, which is you are using
|
||||
@ -274,6 +266,10 @@ which then it will look like
|
||||

|
||||
|
||||
|
||||
:::info
|
||||
There is also dedicated example for this in the [cornerstone3D examples](https://www.cornerstonejs.org/live-examples/dynamicallyaddannotations).
|
||||
:::
|
||||
|
||||
|
||||
## How do I sort the series in the study panel by a specific value
|
||||
|
||||
|
||||
@ -97,6 +97,35 @@ import { ReactComponent as arrowDown } from './../../assets/icons/arrow-down.svg
|
||||
We have removed the Polyfill.io script from the Viewer. If you require polyfills, you can add them to your project manually. This change primarily affects Internet Explorer, which Microsoft has already [ended support for](https://learn.microsoft.com/en-us/lifecycle/faq/internet-explorer-microsoft-edge#is-internet-explorer-11-the-last-version-of-internet-explorer-).
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Webpack changes
|
||||
|
||||
We previously were copying dicom-image-loader wasm files to the public folder via
|
||||
|
||||
```js
|
||||
// platform/app/.webpack/webpack.pwa.js
|
||||
{
|
||||
from: '../../../node_modules/@cornerstonejs/dicom-image-loader/dist/dynamic-import',
|
||||
to: DIST_DIR,
|
||||
},
|
||||
```
|
||||
|
||||
but now after our upgrade to Cornerstone 3D 2.0, we don't need to do this anymore.
|
||||
|
||||
|
||||
---
|
||||
## Scroll utility
|
||||
|
||||
|
||||
The `jumpToSlice` utility has been relocated from `@cornerstonejs/tools` utilities to `@cornerstonejs/core/utilities`.
|
||||
|
||||
migration
|
||||
|
||||
```js
|
||||
import { jumpToSlice } from '@cornerstonejs/core/utilities';
|
||||
```
|
||||
|
||||
|
||||
---
|
||||
|
||||
@ -178,9 +207,19 @@ Now:
|
||||
|
||||
---
|
||||
|
||||
## CustomizationService
|
||||
|
||||
The `CustomizationService` uses `contentF` instead of `content`.
|
||||
|
||||
So make sure your customizations are updated accordingly.
|
||||
|
||||
---
|
||||
|
||||
## SidePanel auto switch if open
|
||||
|
||||
In `basic viewer` mode, if the side panel is open and the segmentation panel is active, adding a measurement will automatically switch to the measurement panel. This switch won't occur if the side panel is closed. To enable or disable this feature, adjust your mode configuration accordingly.
|
||||
In `basic viewer` mode, when the side panel is open and the segmentation panel is active, adding a measurement will automatically switch to the measurement panel. This switch won't happen if the side panel is closed. To enable or disable this feature, adjust your mode configuration accordingly.
|
||||
|
||||
To prevent this behavior, remove the following code from your mode:
|
||||
|
||||
```js
|
||||
panelService.addActivatePanelTriggers('your.panel.id', [
|
||||
|
||||
@ -2,9 +2,6 @@
|
||||
title: UI
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
## New Components
|
||||
|
||||
You can explore our new playground at `docs.ohif.org/ui` to see the latest components and their properties. We haven't provided a migration guide yet because the old components are still available. Feel free to update your codebase, including custom extensions and UI, to use the new Button, Dropdown, Icons, and other new components from `@ohif/ui-next`. The old methods (importing from `@ohif/ui`) will continue to work for now. However, the new components have a slightly different API, and we plan to deprecate the old components in a future release, as we see the new ones as the future of OHIF.
|
||||
@ -147,3 +144,13 @@ All the DropDown and Icons are now in the @ohif/ui-next package.
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
## ui, ui-next configs
|
||||
|
||||
We currently have two component libraries that we plan to merge in the future, so we need to maintain both configurations. If your styles aren't applying correctly, ensure you update both `platform/ui-next/tailwind.config.js` and `platform/ui/tailwind.config.js`.
|
||||
|
||||
|
||||
### addIcon from ui-next
|
||||
|
||||
if you add custom icons, you may need to add them using a new `addIcon` utility which adds the icon to both `ui` and `ui-next`.
|
||||
|
||||
@ -84,7 +84,7 @@ important api endpoints that you need to implement:
|
||||
- `initialize`: This method is called when the data source is first created in the mode.tsx, it is used to initialize the data source and set the configuration. For instance, `dicomwebDatasource` uses this method to grab the StudyInstanceUID from the URL and set it as the active study, as opposed to `dicomJSONDatasource` which uses url in the browser to fetch the data and store it in a cache
|
||||
- `query.studies.search`: This is used in the study panel on the left to fetch the prior studies for the same MRN which is then used to display on the `All` tab. it is also used in the Worklist to show all the studies from the server.
|
||||
- `query.series.search`: This is used to fetch the series information for a given study that is expanded in the Worklist.
|
||||
- `retrieve.bulkDataURI`: used to render RTSTUCTURESET in the viewport.
|
||||
- `retrieve.bulkDataURI`: used to render RTSTUCTURESET in the viewport. It is an object that contains `enabled` as property and other options that are specific to the data source.
|
||||
- `retrieve.series.metadata`: It is a crucial end point that is used to fetch series level metadata which for hanging displaySets and displaySet creation.
|
||||
- `store.dicom`: If you don't need store functionality, you can skip this method. This is used to store the data in the backend.
|
||||
|
||||
|
||||
@ -137,7 +137,52 @@ this pattern, where multiple toolbar buttons are using the same evaluator but wi
|
||||
},
|
||||
```
|
||||
|
||||
|
||||
#### Viewport and Modality Support Evaluation
|
||||
|
||||
The toolbar system now uses a more robust approach for evaluating button states based on viewport types and modalities:
|
||||
|
||||
**Viewport Type Support**:
|
||||
|
||||
Use `evaluate.viewport.supported` to disable buttons for specific viewport types:
|
||||
|
||||
```js
|
||||
{
|
||||
name: 'evaluate.viewport.supported',
|
||||
unsupportedViewportTypes: ['volume3d', 'video', 'sm']
|
||||
}
|
||||
```
|
||||
|
||||
**Modality Support**:
|
||||
Use `evaluate.modality.supported` to control button state based on modalities:
|
||||
|
||||
```js
|
||||
{
|
||||
name: 'evaluate.modality.supported',
|
||||
supportedModalities: ['CT', 'MR'], // Enable only for these modalities
|
||||
// OR
|
||||
unsupportedModalities: ['US'] // Disable for these modalities
|
||||
}
|
||||
```
|
||||
|
||||
#### Composing evaluators
|
||||
Multiple evaluators can be combined to create complex conditions:
|
||||
|
||||
```js
|
||||
evaluate: [
|
||||
'evaluate.cine',
|
||||
{
|
||||
name: 'evaluate.viewport.supported',
|
||||
unsupportedViewportTypes: ['volume3d']
|
||||
},
|
||||
{
|
||||
name: 'evaluate.modality.supported',
|
||||
supportedModalities: ['CT']
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
This evaluation system provides more precise control over when toolbar buttons are enabled or disabled based on the active viewport's characteristics.
|
||||
|
||||
You can choose to set up multiple evaluators for a single button. This comes in handy when you need to assess the button according to various conditions. For example, we aim to prevent the Cine player from showing up on the 3D viewport, so we have:
|
||||
|
||||
|
||||
@ -5,50 +5,141 @@ sidebar_label: Segmentation Service
|
||||
|
||||
# Segmentation Service
|
||||
|
||||
## Overview
|
||||
|
||||
Using Segmentation Service you can create, edit and delete segmentation data, and
|
||||
change appearance of the segmentation including color, opacity and visibility.
|
||||
|
||||
Segmentations in OHIF are based on the Segmentations in Cornerstone3D. You can
|
||||
read more about it in the [Cornerstone Segmentation](https://www.cornerstonejs.org/docs/concepts/cornerstone-tools/segmentation/). OHIF currently only supports
|
||||
one representation of the segmentation data.
|
||||
|
||||
## Events
|
||||
|
||||
There are seven events that get publish in `MeasurementService`:
|
||||
```typescript
|
||||
SEGMENTATION_MODIFIED // When a segmentation is updated
|
||||
SEGMENTATION_DATA_MODIFIED // When segmentation data changes
|
||||
SEGMENTATION_ADDED // When new segmentation is added
|
||||
SEGMENTATION_REMOVED // When segmentation is removed
|
||||
SEGMENT_LOADING_COMPLETE // When segment group adds pixel data to volume
|
||||
SEGMENTATION_LOADING_COMPLETE // When full segmentation volume is filled
|
||||
```
|
||||
|
||||
| Event | Description |
|
||||
| --------------------- | ------------------------------------------------------ |
|
||||
| SEGMENTATION_MODIFIED | Fires when a segmentation is updated e.g., segment added, removed etc.|
|
||||
| SEGMENTATION_DATA_MODIFIED | Fires when the segmentation data changes |
|
||||
| SEGMENTATION_ADDED | Fires when a new segmentation is added to OHIF |
|
||||
| SEGMENTATION_REMOVED | Fires when a segmentation is removed from OHIF |
|
||||
| SEGMENT_LOADING_COMPLETE | Fires when a segment group adds its pixel data to the volume |
|
||||
| SEGMENTATION_LOADING_COMPLETE | Fires when the full segmentation volume is filled with its segments |
|
||||
## Core APIs
|
||||
|
||||
### Creation Methods
|
||||
|
||||
## API
|
||||
```typescript
|
||||
createLabelmapForDisplaySet(
|
||||
displaySet,
|
||||
{
|
||||
segmentationId?: string,
|
||||
label: string,
|
||||
segments?: {
|
||||
[segmentIndex: number]: Partial<Segment>
|
||||
}
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
### Segmentation Creation
|
||||
### Segmentation Management
|
||||
|
||||
- `createEmptyLabelmapForDisplaySetUID`: based on a reference displaySet, create a new segmentation. E.g., create a new segmentation based on a CT series
|
||||
- `createSegmentationForSEGDisplaySet`: given a segDisplaySet loaded by a sopClassHandler, create a new segmentation
|
||||
- `addSegmentationRepresentationToToolGroup`: given the toolGroupId, add the given segmentationId to the toolGroup.
|
||||
```typescript
|
||||
setActiveSegmentation(viewportId, segmentationId)
|
||||
getSegmentations()
|
||||
getSegmentation(segmentationId)
|
||||
jumpToSegmentCenter(segmentationId, segmentIndex, viewportId)
|
||||
highlightSegment(segmentationId, segmentIndex, viewportId)
|
||||
```
|
||||
|
||||
### Segment Operations
|
||||
|
||||
### Segmentation Behavior
|
||||
```typescript
|
||||
addSegment(segmentationId, {
|
||||
segmentIndex?: number,
|
||||
label?: string,
|
||||
color?: [number, number, number, number], // RGBA
|
||||
visibility?: boolean,
|
||||
isLocked?: boolean,
|
||||
active?: boolean
|
||||
})
|
||||
|
||||
- setActiveSegmentationForToolGroup, getSegmentations, getSegmentation, jumpToSegmentCenter, highlightSegment
|
||||
setSegmentColor(viewportId, segmentationId, segmentIndex, color)
|
||||
setSegmentVisibility(viewportId, segmentationId, segmentIndex, visibility)
|
||||
```
|
||||
|
||||
## Data Structures
|
||||
|
||||
### Segment Behavior
|
||||
### Segmentation Object
|
||||
|
||||
- setSegmentLocked, removeSegment, addSegment, setSegmentLocked, setSegmentLabel, setActiveSegment,
|
||||
setSegmentRGBAColor
|
||||
```typescript
|
||||
interface Segmentation {
|
||||
segmentationId: string;
|
||||
label: string;
|
||||
segments: {
|
||||
[segmentIndex: number]: {
|
||||
segmentIndex: number;
|
||||
label: string;
|
||||
locked: boolean;
|
||||
cachedStats: { [key: string]: unknown };
|
||||
active: boolean;
|
||||
}
|
||||
};
|
||||
representationData: RepresentationsData;
|
||||
}
|
||||
```
|
||||
|
||||
### Segmentation Configuration
|
||||
## Code Examples
|
||||
|
||||
Setters
|
||||
### Creating a Segmentation
|
||||
|
||||
- setSegmentVisibility, setSegmentColor, setSegmentRGBA, setSegmentOpacity, toggleSegmentationVisibility,
|
||||
```typescript
|
||||
const displaySet = displaySetService.getDisplaySetByUID(displaySetUID);
|
||||
const segmentationId = await segmentationService.createLabelmapForDisplaySet(
|
||||
displaySet,
|
||||
{
|
||||
label: 'New Segmentation',
|
||||
segments: {
|
||||
1: {
|
||||
label: 'First Segment',
|
||||
active: true
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
### Managing Active Segmentations
|
||||
|
||||
```typescript
|
||||
segmentationService.setActiveSegmentation('viewport-1', segmentationId);
|
||||
```
|
||||
|
||||
### Adding Segments
|
||||
|
||||
```typescript
|
||||
segmentationService.addSegment(segmentationId, {
|
||||
label: 'Tumor',
|
||||
color: [255, 0, 0, 255], // RGBA format
|
||||
active: true
|
||||
});
|
||||
```
|
||||
|
||||
### Visibility Management
|
||||
|
||||
```typescript
|
||||
// Set segment visibility
|
||||
segmentationService.setSegmentVisibility(
|
||||
'viewport-1',
|
||||
segmentationId,
|
||||
1, // segmentIndex
|
||||
true // visible
|
||||
);
|
||||
|
||||
// Get viewport IDs with segmentation
|
||||
const viewportIds = segmentationService.getViewportIdsWithSegmentation(segmentationId);
|
||||
```
|
||||
|
||||
### Segment Styling
|
||||
|
||||
```typescript
|
||||
// Set segment color
|
||||
segmentationService.setSegmentColor(
|
||||
'viewport-1',
|
||||
segmentationId,
|
||||
1, // segmentIndex
|
||||
[255, 0, 0, 255] // RGBA
|
||||
);
|
||||
```
|
||||
|
||||
@ -41,16 +41,16 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@docusaurus/core": "3.6.0",
|
||||
"@docusaurus/faster": "3.6.0",
|
||||
"@docusaurus/plugin-client-redirects": "3.6.0",
|
||||
"@docusaurus/plugin-google-gtag": "3.6.0",
|
||||
"@docusaurus/plugin-ideal-image": "3.6.0",
|
||||
"@docusaurus/plugin-pwa": "3.6.0",
|
||||
"@docusaurus/preset-classic": "3.6.0",
|
||||
"@docusaurus/remark-plugin-npm2yarn": "3.6.0",
|
||||
"@docusaurus/theme-classic": "3.6.0",
|
||||
"@docusaurus/theme-live-codeblock": "3.6.0",
|
||||
"@docusaurus/core": "3.6.1",
|
||||
"@docusaurus/faster": "3.6.1",
|
||||
"@docusaurus/plugin-client-redirects": "3.6.1",
|
||||
"@docusaurus/plugin-google-gtag": "3.6.1",
|
||||
"@docusaurus/plugin-ideal-image": "3.6.1",
|
||||
"@docusaurus/plugin-pwa": "3.6.1",
|
||||
"@docusaurus/preset-classic": "3.6.1",
|
||||
"@docusaurus/remark-plugin-npm2yarn": "3.6.1",
|
||||
"@docusaurus/theme-classic": "3.6.1",
|
||||
"@docusaurus/theme-live-codeblock": "3.6.1",
|
||||
"@mdx-js/react": "3.0.1",
|
||||
"@radix-ui/react-accordion": "^1.2.0",
|
||||
"@radix-ui/react-checkbox": "^1.1.1",
|
||||
|
||||
@ -139,14 +139,7 @@ const DataRow: React.FC<DataRowProps> = ({
|
||||
className="whitespace-pre-wrap"
|
||||
>
|
||||
{indentation}
|
||||
{cleanText.includes(':') ? (
|
||||
<>
|
||||
<span className="font-medium">{cleanText.split(':')[0]}:</span>
|
||||
{cleanText.split(':')[1]}
|
||||
</>
|
||||
) : (
|
||||
<span className="font-medium">{cleanText}</span>
|
||||
)}
|
||||
<span className="font-medium">{cleanText}</span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@ -199,14 +192,14 @@ const DataRow: React.FC<DataRowProps> = ({
|
||||
{/* Hover Overlay */}
|
||||
<div className="bg-primary/20 pointer-events-none absolute inset-0 opacity-0 transition-opacity group-hover:opacity-100"></div>
|
||||
|
||||
{/* Number Box */}
|
||||
<div
|
||||
className={`flex h-7 max-h-7 w-7 flex-shrink-0 items-center justify-center rounded-l border-r border-black text-base ${
|
||||
isSelected ? 'bg-highlight text-black' : 'bg-muted text-muted-foreground'
|
||||
} overflow-hidden`}
|
||||
>
|
||||
{number}
|
||||
</div>
|
||||
{/* Number Box */}
|
||||
<div
|
||||
className={`flex h-7 max-h-7 w-7 flex-shrink-0 items-center justify-center rounded-l border-r border-black text-base ${
|
||||
isSelected ? 'bg-highlight text-black' : 'bg-muted text-muted-foreground'
|
||||
} overflow-hidden`}
|
||||
>
|
||||
{number}
|
||||
</div>
|
||||
|
||||
{/* Color Circle (Optional) */}
|
||||
{colorHex && (
|
||||
@ -313,10 +306,16 @@ const DataRow: React.FC<DataRowProps> = ({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{details && details.primary?.length > 0 && (
|
||||
{/* Details Section */}
|
||||
{details && (details.primary?.length > 0 || details.secondary?.length > 0) && (
|
||||
<div className="ml-7 px-2 py-2">
|
||||
<div className="text-secondary-foreground text-base leading-normal">
|
||||
{renderDetails(details.primary)}
|
||||
<div className="text-secondary-foreground flex items-center gap-1 text-base leading-normal">
|
||||
{details.primary?.length > 0 && renderDetails(details.primary)}
|
||||
{details.secondary?.length > 0 && (
|
||||
<div className="text-muted-foreground ml-auto text-sm">
|
||||
{renderDetails(details.secondary)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@ -34,7 +34,7 @@ export const SegmentationSegments: React.FC<{
|
||||
}
|
||||
|
||||
const segmentCount = Object.keys(representationToUse.segments).length;
|
||||
const height = mode === 'collapsed' ? 'h-[600px]' : `h-[${segmentCount * 200}px]`;
|
||||
const height = mode === 'collapsed' ? 'h-[900px]' : `h-[${segmentCount * 200}px]`;
|
||||
|
||||
return (
|
||||
<ScrollArea
|
||||
|
||||
@ -398,17 +398,6 @@ SidePanel.propTypes = {
|
||||
side: PropTypes.oneOf(['left', 'right']).isRequired,
|
||||
className: PropTypes.string,
|
||||
activeTabIndex: PropTypes.number,
|
||||
tabs: PropTypes.oneOfType([
|
||||
PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
iconName: PropTypes.string.isRequired,
|
||||
iconLabel: PropTypes.string.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
label: PropTypes.string.isRequired,
|
||||
content: PropTypes.func, // TODO: Should be node, but it keeps complaining?
|
||||
})
|
||||
),
|
||||
]),
|
||||
onOpen: PropTypes.func,
|
||||
onClose: PropTypes.func,
|
||||
onActiveTabIndexChange: PropTypes.func,
|
||||
|
||||
@ -4,10 +4,6 @@
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
* {
|
||||
min-height: 0 !important;
|
||||
}
|
||||
|
||||
/* OHIF Theme */
|
||||
|
||||
@layer base {
|
||||
|
||||
@ -237,7 +237,7 @@ const SidePanel = ({
|
||||
content={getToolTipContent(childComponent.label, childComponent.disabled)}
|
||||
className={classnames(
|
||||
'flex items-center',
|
||||
side === 'left' ? 'justify-end ' : 'justify-start '
|
||||
side === 'left' ? 'justify-end' : 'justify-start'
|
||||
)}
|
||||
>
|
||||
<div
|
||||
@ -292,7 +292,7 @@ const SidePanel = ({
|
||||
const numCols = getNumGridColumns(tabs.length, gridWidth);
|
||||
|
||||
return (
|
||||
<div className={classnames('flex grow ', side === 'right' ? 'justify-start' : 'justify-end')}>
|
||||
<div className={classnames('flex grow', side === 'right' ? 'justify-start' : 'justify-end')}>
|
||||
<div
|
||||
className={classnames('bg-primary-dark text-primary-active flex flex-wrap')}
|
||||
style={getGridStyle(side, tabs.length, gridWidth, expandedWidth)}
|
||||
@ -354,7 +354,7 @@ const SidePanel = ({
|
||||
return (
|
||||
<div
|
||||
className={classnames(
|
||||
'text-primary-active flex grow cursor-pointer select-none justify-center self-center text-[13px]'
|
||||
'text-primary-active flex grow cursor-pointer select-none justify-center self-center text-[13px]'
|
||||
)}
|
||||
style={{
|
||||
...(side === 'left'
|
||||
@ -371,7 +371,7 @@ const SidePanel = ({
|
||||
|
||||
const getOpenStateComponent = () => {
|
||||
return (
|
||||
<div className="bg-primary-dark flex select-none rounded-t pt-1.5 pb-[2px] ">
|
||||
<div className="bg-primary-dark flex select-none rounded-t pt-1.5 pb-[2px]">
|
||||
{getCloseIcon()}
|
||||
{tabs.length === 1 ? getOneTabComponent() : getTabGridComponent()}
|
||||
</div>
|
||||
|
||||
@ -5,10 +5,6 @@
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
* {
|
||||
min-height: 0 !important;
|
||||
}
|
||||
|
||||
@layer base {
|
||||
html {
|
||||
font-family: 'Inter', sans-serif;
|
||||
|
||||
553
yarn.lock
553
yarn.lock
@ -2580,10 +2580,10 @@
|
||||
resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9"
|
||||
integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==
|
||||
|
||||
"@cornerstonejs/adapters@^2.2.4":
|
||||
version "2.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@cornerstonejs/adapters/-/adapters-2.2.4.tgz#6f5edf17dc5f76cb6c80d67a4b70c38c1ca05700"
|
||||
integrity sha512-sWatnhu93NjaT8MsrJIsexpxzFrUmtxrS6lSBca9CWNDMLR1t8boff6fmvGKE8TYbQkPQZrytRJBSw5O6pWdMg==
|
||||
"@cornerstonejs/adapters@^2.2.20":
|
||||
version "2.2.20"
|
||||
resolved "https://registry.yarnpkg.com/@cornerstonejs/adapters/-/adapters-2.2.20.tgz#82fd0775a6ac4e138bda4f3dad412593133b16a9"
|
||||
integrity sha512-o9c3eTJa7D0wgdkAdg33/BET5+BgM5qjt6Xmd/QSXsghPyJcmvnxIzKS+upt2///u+f8q4aaiL3dgsVzNc6L9g==
|
||||
dependencies:
|
||||
"@babel/runtime-corejs2" "^7.17.8"
|
||||
buffer "^6.0.3"
|
||||
@ -2616,19 +2616,19 @@
|
||||
resolved "https://registry.yarnpkg.com/@cornerstonejs/codec-openjph/-/codec-openjph-2.4.5.tgz#8690b61a86fa53ef38a70eee9d665a79229517c0"
|
||||
integrity sha512-MZCUy8VG0VG5Nl1l58+g+kH3LujAzLYTfJqkwpWI2gjSrGXnP6lgwyy4GmPRZWVoS40/B1LDNALK905cNWm+sg==
|
||||
|
||||
"@cornerstonejs/core@^2.2.4":
|
||||
version "2.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@cornerstonejs/core/-/core-2.2.4.tgz#eeb4e383a332e43186299cb19ddd46dad1013437"
|
||||
integrity sha512-nw14sTuz02o2W8a0WT0dH4J1B7iZ4KZU5r0KDnYkpDHjL1Y30lmSt098Pxb4Z9Xj+GJYunlWv962RtVhnWbSZA==
|
||||
"@cornerstonejs/core@^2.2.20":
|
||||
version "2.2.20"
|
||||
resolved "https://registry.yarnpkg.com/@cornerstonejs/core/-/core-2.2.20.tgz#a39176c0f832ce2d91f414a2f06010c54c3b99b0"
|
||||
integrity sha512-1gfARz1tqoAnic1rTGILF9MbwC0YICCNWS+k5vCkf+1ZX3XYepMt3bV3GPPAcTDJ2t6t20Ii1xdKueDn3BSIXw==
|
||||
dependencies:
|
||||
"@kitware/vtk.js" "32.1.0"
|
||||
"@kitware/vtk.js" "32.1.1"
|
||||
comlink "^4.4.1"
|
||||
gl-matrix "^3.4.3"
|
||||
|
||||
"@cornerstonejs/dicom-image-loader@^2.2.4":
|
||||
version "2.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@cornerstonejs/dicom-image-loader/-/dicom-image-loader-2.2.4.tgz#117635b11a0230381fe31a5119271b472f7048d5"
|
||||
integrity sha512-DwRZrTaVrrH7aGqFibcL+Ijnygtd3sxovxREzHWqGrmmxpwsm+aA9Z5nXeg58hk5Kvd0Zt8iwlrtcnTeD2DPiw==
|
||||
"@cornerstonejs/dicom-image-loader@^2.2.20":
|
||||
version "2.2.20"
|
||||
resolved "https://registry.yarnpkg.com/@cornerstonejs/dicom-image-loader/-/dicom-image-loader-2.2.20.tgz#3d1d448ac2c7010ae29359209f5a6b1790777930"
|
||||
integrity sha512-pYyYzPbbwOU9tH84WAhBK/+XdJ/Gc3hYfsrsuGk3ufVsdjRywvjGviSOYN4My0w++ezanaSFdPNcghtqdL8etQ==
|
||||
dependencies:
|
||||
"@cornerstonejs/codec-charls" "^1.2.3"
|
||||
"@cornerstonejs/codec-libjpeg-turbo-8bit" "^1.2.2"
|
||||
@ -2639,10 +2639,10 @@
|
||||
pako "^2.0.4"
|
||||
uuid "^9.0.0"
|
||||
|
||||
"@cornerstonejs/tools@^2.2.4":
|
||||
version "2.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@cornerstonejs/tools/-/tools-2.2.4.tgz#3fa5e99daffc73434d7385885dda09e17820756c"
|
||||
integrity sha512-pEqJzAp4/ZtVmWqPG7C/hH/09dt6OBoRq5fiEJE/mxJXbe77FeDq5zQy8Irv7IkDpXpnc8kL+6L9Zb5awc3uRA==
|
||||
"@cornerstonejs/tools@^2.2.20":
|
||||
version "2.2.20"
|
||||
resolved "https://registry.yarnpkg.com/@cornerstonejs/tools/-/tools-2.2.20.tgz#d2fcbc1b6f585f4094bb5d03d3ae87862e1df092"
|
||||
integrity sha512-rS7KNfLjwtZ0MzP9eT5EDKBDoEh/Nt5htJxj9b/BvL2W6X/vyF361tWYf/L2dIo0NdR6LBYds3Gdm31y+b7drA==
|
||||
dependencies:
|
||||
"@types/offscreencanvas" "2019.7.3"
|
||||
comlink "^4.4.1"
|
||||
@ -2806,10 +2806,10 @@
|
||||
"@docsearch/css" "3.6.2"
|
||||
algoliasearch "^4.19.1"
|
||||
|
||||
"@docusaurus/babel@3.6.0":
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/babel/-/babel-3.6.0.tgz#735a003207925bd782dd08ffa5d8b3503c1f8d72"
|
||||
integrity sha512-7CsoQFiadoq7AHSUIQNkI/lGfg9AQ2ZBzsf9BqfZGXkHwWDy6twuohEaG0PgQv1npSRSAB2dioVxhRSErnqKNA==
|
||||
"@docusaurus/babel@3.6.1":
|
||||
version "3.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/babel/-/babel-3.6.1.tgz#5f48a275934b8164ccac3a6fd1fca3741374c884"
|
||||
integrity sha512-JcKaunW8Ml2nTnfnvFc55T00Y+aCpNWnf1KY/gG+wWxHYDH0IdXOOz+k6NAlEAerW8+VYLfUqRIqHZ7N/DVXvQ==
|
||||
dependencies:
|
||||
"@babel/core" "^7.25.9"
|
||||
"@babel/generator" "^7.25.9"
|
||||
@ -2821,23 +2821,23 @@
|
||||
"@babel/runtime" "^7.25.9"
|
||||
"@babel/runtime-corejs3" "^7.25.9"
|
||||
"@babel/traverse" "^7.25.9"
|
||||
"@docusaurus/logger" "3.6.0"
|
||||
"@docusaurus/utils" "3.6.0"
|
||||
"@docusaurus/logger" "3.6.1"
|
||||
"@docusaurus/utils" "3.6.1"
|
||||
babel-plugin-dynamic-import-node "^2.3.3"
|
||||
fs-extra "^11.1.1"
|
||||
tslib "^2.6.0"
|
||||
|
||||
"@docusaurus/bundler@3.6.0":
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/bundler/-/bundler-3.6.0.tgz#bdd060ba4d009211348e4e973a3bf4861cf0996b"
|
||||
integrity sha512-o5T9HXkPKH0OQAifTxEXaebcO8kaz3tU1+wlIShZ2DKJHlsyWX3N4rToWBHroWnV/ZCT2XN3kLRzXASqrnb9Tw==
|
||||
"@docusaurus/bundler@3.6.1":
|
||||
version "3.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/bundler/-/bundler-3.6.1.tgz#240343d31f39638f987caf54793c09820270ecd5"
|
||||
integrity sha512-vHSEx8Ku9x/gfIC6k4xb8J2nTxagLia0KvZkPZhxfkD1+n8i+Dj4BZPWTmv+kCA17RbgAvECG0XRZ0/ZEspQBQ==
|
||||
dependencies:
|
||||
"@babel/core" "^7.25.9"
|
||||
"@docusaurus/babel" "3.6.0"
|
||||
"@docusaurus/cssnano-preset" "3.6.0"
|
||||
"@docusaurus/logger" "3.6.0"
|
||||
"@docusaurus/types" "3.6.0"
|
||||
"@docusaurus/utils" "3.6.0"
|
||||
"@docusaurus/babel" "3.6.1"
|
||||
"@docusaurus/cssnano-preset" "3.6.1"
|
||||
"@docusaurus/logger" "3.6.1"
|
||||
"@docusaurus/types" "3.6.1"
|
||||
"@docusaurus/utils" "3.6.1"
|
||||
autoprefixer "^10.4.14"
|
||||
babel-loader "^9.2.1"
|
||||
clean-css "^5.3.2"
|
||||
@ -2858,18 +2858,18 @@
|
||||
webpack "^5.95.0"
|
||||
webpackbar "^6.0.1"
|
||||
|
||||
"@docusaurus/core@3.6.0":
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/core/-/core-3.6.0.tgz#b23fc7e253a49cc3e5ac9e091354f497cc0b101b"
|
||||
integrity sha512-lvRgMoKJJSRDt9+HhAqFcICV4kp/mw1cJJrLxIw4Q2XZnFGM1XUuwcbuaqWmGog+NcOLZaPCcCtZbn60EMCtjQ==
|
||||
"@docusaurus/core@3.6.1":
|
||||
version "3.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/core/-/core-3.6.1.tgz#260d78e1eb7129ccb441fa944b5f7e6f492ac6cb"
|
||||
integrity sha512-cDKxPihiM2z7G+4QtpTczS7uxNfNG6naSqM65OmAJET0CFRHbc9mDlLFtQF0lsVES91SHqfcGaaLZmi2FjdwWA==
|
||||
dependencies:
|
||||
"@docusaurus/babel" "3.6.0"
|
||||
"@docusaurus/bundler" "3.6.0"
|
||||
"@docusaurus/logger" "3.6.0"
|
||||
"@docusaurus/mdx-loader" "3.6.0"
|
||||
"@docusaurus/utils" "3.6.0"
|
||||
"@docusaurus/utils-common" "3.6.0"
|
||||
"@docusaurus/utils-validation" "3.6.0"
|
||||
"@docusaurus/babel" "3.6.1"
|
||||
"@docusaurus/bundler" "3.6.1"
|
||||
"@docusaurus/logger" "3.6.1"
|
||||
"@docusaurus/mdx-loader" "3.6.1"
|
||||
"@docusaurus/utils" "3.6.1"
|
||||
"@docusaurus/utils-common" "3.6.1"
|
||||
"@docusaurus/utils-validation" "3.6.1"
|
||||
boxen "^6.2.1"
|
||||
chalk "^4.1.2"
|
||||
chokidar "^3.5.3"
|
||||
@ -2907,21 +2907,22 @@
|
||||
webpack-dev-server "^4.15.2"
|
||||
webpack-merge "^6.0.1"
|
||||
|
||||
"@docusaurus/cssnano-preset@3.6.0":
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/cssnano-preset/-/cssnano-preset-3.6.0.tgz#02378e53e9568ed5fc8871d4fc158ea96fd7421c"
|
||||
integrity sha512-h3jlOXqqzNSoU+C4CZLNpFtD+v2xr1UBf4idZpwMgqid9r6lb5GS7tWKnQnauio6OipacbHbDXEX3JyT1PlDkg==
|
||||
"@docusaurus/cssnano-preset@3.6.1":
|
||||
version "3.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/cssnano-preset/-/cssnano-preset-3.6.1.tgz#dc07b15f37d5c7bc1e59255ce0fa8825dde2dfb7"
|
||||
integrity sha512-ZxYUmNeyQHW2w4/PJ7d07jQDuxzmKr9uPAQ6IVe5dTkeIeV0mDBB3jOLeJkNoI42Ru9JKEqQ9aVDtM9ct6QHnw==
|
||||
dependencies:
|
||||
cssnano-preset-advanced "^6.1.2"
|
||||
postcss "^8.4.38"
|
||||
postcss-sort-media-queries "^5.2.0"
|
||||
tslib "^2.6.0"
|
||||
|
||||
"@docusaurus/faster@3.6.0":
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/faster/-/faster-3.6.0.tgz#70540e689fd16e26e6105fe689a1347b8ac93834"
|
||||
integrity sha512-9X06/KHD3f4CKm0SjZQIK3UDE/XvouAMiAlYMPV5LprubFlxVQecZG9QnfOe7VIfUh9IuPiDPuGg17yy0efwww==
|
||||
"@docusaurus/faster@3.6.1":
|
||||
version "3.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/faster/-/faster-3.6.1.tgz#f564abe9904c4132ca32164012f8427270c257c8"
|
||||
integrity sha512-W3a9m7Q/fEeOpOw9/XktLCHRtp1sV2AdZWMCjH3kP1jY1TDyLFFiHJ0+1uwVpOw4/oPJqZSTRKP+IdW4+65NgQ==
|
||||
dependencies:
|
||||
"@docusaurus/types" "3.6.1"
|
||||
"@rspack/core" "^1.0.14"
|
||||
"@swc/core" "^1.7.39"
|
||||
"@swc/html" "^1.7.39"
|
||||
@ -2931,33 +2932,33 @@
|
||||
tslib "^2.6.0"
|
||||
webpack "^5.95.0"
|
||||
|
||||
"@docusaurus/logger@3.6.0":
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/logger/-/logger-3.6.0.tgz#c7349c2636087f55f573a60a3c7f69b87d59974d"
|
||||
integrity sha512-BcQhoXilXW0607cH/kO6P5Gt5KxCGfoJ+QDKNf3yO2S09/RsITlW+0QljXPbI3DklTrHrhRDmgGk1yX4nUhWTA==
|
||||
"@docusaurus/logger@3.6.1":
|
||||
version "3.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/logger/-/logger-3.6.1.tgz#724b7f9d8c435c9933d52792458659471ec90919"
|
||||
integrity sha512-OvetI/nnOMBSqCkUzKAQhnIjhxduECK4qTu3tq/8/h/qqvLsvKURojm04WPE54L+Uy+UXMas0hnbBJd8zDlEOw==
|
||||
dependencies:
|
||||
chalk "^4.1.2"
|
||||
tslib "^2.6.0"
|
||||
|
||||
"@docusaurus/lqip-loader@3.6.0":
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/lqip-loader/-/lqip-loader-3.6.0.tgz#c40cbe74690455e5c65749d4a9a2bc00806a91a9"
|
||||
integrity sha512-jEQjnKAjhgyZ/aQf0Tbl3eDpp1j0C/GojE/cv2Bad89o+luV1OAOs9UHDRyKwWQfN+se0D9kFxkfsfwYxMpI8A==
|
||||
"@docusaurus/lqip-loader@3.6.1":
|
||||
version "3.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/lqip-loader/-/lqip-loader-3.6.1.tgz#b5a4956b8906b2087e2f9429c63ddaff184f8f77"
|
||||
integrity sha512-H/VVvnvFupFhQ81FuTyA/XHxEZPKh99T6Wg6KgN+/yvcn7869RdgrlDhKDnXZ7j2u80eFsVNjAcPfW1cSAtK6A==
|
||||
dependencies:
|
||||
"@docusaurus/logger" "3.6.0"
|
||||
"@docusaurus/logger" "3.6.1"
|
||||
file-loader "^6.2.0"
|
||||
lodash "^4.17.21"
|
||||
sharp "^0.32.3"
|
||||
tslib "^2.6.0"
|
||||
|
||||
"@docusaurus/mdx-loader@3.6.0":
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/mdx-loader/-/mdx-loader-3.6.0.tgz#f8ba7af9d59473a7182f6a9307e0432f8dce905b"
|
||||
integrity sha512-GhRzL1Af/AdSSrGesSPOU/iP/aXadTGmVKuysCxZDrQR2RtBtubQZ9aw+KvdFVV7R4K/CsbgD6J5oqrXlEPk3Q==
|
||||
"@docusaurus/mdx-loader@3.6.1":
|
||||
version "3.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/mdx-loader/-/mdx-loader-3.6.1.tgz#6482e6f2f32ccab4a74d8b64d7eeec4fdf9be475"
|
||||
integrity sha512-KPIsYi0S3X3/rNrW3V1fgOu5t6ahYWc31zTHHod8pacFxdmk9Uf6uuw+Jd6Cly1ilgal+41Ku+s0gmMuqKqiqg==
|
||||
dependencies:
|
||||
"@docusaurus/logger" "3.6.0"
|
||||
"@docusaurus/utils" "3.6.0"
|
||||
"@docusaurus/utils-validation" "3.6.0"
|
||||
"@docusaurus/logger" "3.6.1"
|
||||
"@docusaurus/utils" "3.6.1"
|
||||
"@docusaurus/utils-validation" "3.6.1"
|
||||
"@mdx-js/mdx" "^3.0.0"
|
||||
"@slorber/remark-comment" "^1.0.0"
|
||||
escape-html "^1.0.3"
|
||||
@ -2994,12 +2995,12 @@
|
||||
react-helmet-async "*"
|
||||
react-loadable "npm:@docusaurus/react-loadable@5.5.2"
|
||||
|
||||
"@docusaurus/module-type-aliases@3.6.0":
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/module-type-aliases/-/module-type-aliases-3.6.0.tgz#44083c34a53db1dde06364b4e7f2d144fa2d5394"
|
||||
integrity sha512-szTrIN/6/fuk0xkf3XbRfdTFJzRQ8d1s3sQj5++58wltrT7v3yn1149oc9ryYjMpRcbsarGloQwMu7ofPe4XPg==
|
||||
"@docusaurus/module-type-aliases@3.6.1":
|
||||
version "3.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/module-type-aliases/-/module-type-aliases-3.6.1.tgz#2780e19411d0c8b16d46a032eae9e60e742ae681"
|
||||
integrity sha512-J+q1jgm7TnEfVIUZImSFeLA1rghb6nwtoB9siHdcgKpDqFJ9/S7xhQL2aEKE7iZMZYzpu+2F390E9A7GkdEJNA==
|
||||
dependencies:
|
||||
"@docusaurus/types" "3.6.0"
|
||||
"@docusaurus/types" "3.6.1"
|
||||
"@types/history" "^4.7.11"
|
||||
"@types/react" "*"
|
||||
"@types/react-router-config" "*"
|
||||
@ -3007,34 +3008,34 @@
|
||||
react-helmet-async "*"
|
||||
react-loadable "npm:@docusaurus/react-loadable@6.0.0"
|
||||
|
||||
"@docusaurus/plugin-client-redirects@3.6.0":
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/plugin-client-redirects/-/plugin-client-redirects-3.6.0.tgz#54155826e9e5da625e296eb93e346c11c1541a78"
|
||||
integrity sha512-LIqRT6dtgxdENQH8XYwOOyxfKuzFD1ayJmIDCp9Yi/rbdcPE4vvTcESLGXOKvcyWZSfyCu+JA8Tyk4qpp+2J0w==
|
||||
"@docusaurus/plugin-client-redirects@3.6.1":
|
||||
version "3.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/plugin-client-redirects/-/plugin-client-redirects-3.6.1.tgz#a035708ff13234a30dbaa84526ab12a102e00d07"
|
||||
integrity sha512-gY1LEQw4zSLSPNVxZk9mDj5ct+sJNux0SiY1PbMiI9sK8xXqkTC7QuRyrxRPelSZX9K4nyhK8PjYbVXAN+GUWQ==
|
||||
dependencies:
|
||||
"@docusaurus/core" "3.6.0"
|
||||
"@docusaurus/logger" "3.6.0"
|
||||
"@docusaurus/utils" "3.6.0"
|
||||
"@docusaurus/utils-common" "3.6.0"
|
||||
"@docusaurus/utils-validation" "3.6.0"
|
||||
"@docusaurus/core" "3.6.1"
|
||||
"@docusaurus/logger" "3.6.1"
|
||||
"@docusaurus/utils" "3.6.1"
|
||||
"@docusaurus/utils-common" "3.6.1"
|
||||
"@docusaurus/utils-validation" "3.6.1"
|
||||
eta "^2.2.0"
|
||||
fs-extra "^11.1.1"
|
||||
lodash "^4.17.21"
|
||||
tslib "^2.6.0"
|
||||
|
||||
"@docusaurus/plugin-content-blog@3.6.0":
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.6.0.tgz#9128175b4c3ce885d9090183d74c60813844ea8d"
|
||||
integrity sha512-o4aT1/E0Ldpzs/hQff5uyoSriAhS/yqBhqSn+fvSw465AaqRsva6O7CZSYleuBq6x2bewyE3QJq2PcTiHhAd8g==
|
||||
"@docusaurus/plugin-content-blog@3.6.1":
|
||||
version "3.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.6.1.tgz#1127d35e1a443e87f9674f955acf7864bc62bfed"
|
||||
integrity sha512-FUmsn3xg/XD/K/4FQd8XHrs92aQdZO5LUtpHnRvO1/6DY87SMz6B6ERAN9IGQQld//M2/LVTHkZy8oVhQZQHIQ==
|
||||
dependencies:
|
||||
"@docusaurus/core" "3.6.0"
|
||||
"@docusaurus/logger" "3.6.0"
|
||||
"@docusaurus/mdx-loader" "3.6.0"
|
||||
"@docusaurus/theme-common" "3.6.0"
|
||||
"@docusaurus/types" "3.6.0"
|
||||
"@docusaurus/utils" "3.6.0"
|
||||
"@docusaurus/utils-common" "3.6.0"
|
||||
"@docusaurus/utils-validation" "3.6.0"
|
||||
"@docusaurus/core" "3.6.1"
|
||||
"@docusaurus/logger" "3.6.1"
|
||||
"@docusaurus/mdx-loader" "3.6.1"
|
||||
"@docusaurus/theme-common" "3.6.1"
|
||||
"@docusaurus/types" "3.6.1"
|
||||
"@docusaurus/utils" "3.6.1"
|
||||
"@docusaurus/utils-common" "3.6.1"
|
||||
"@docusaurus/utils-validation" "3.6.1"
|
||||
cheerio "1.0.0-rc.12"
|
||||
feed "^4.2.2"
|
||||
fs-extra "^11.1.1"
|
||||
@ -3046,20 +3047,20 @@
|
||||
utility-types "^3.10.0"
|
||||
webpack "^5.88.1"
|
||||
|
||||
"@docusaurus/plugin-content-docs@3.6.0":
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.6.0.tgz#15cae4bf81da0b0ddce09d53b10b7209116ea9c2"
|
||||
integrity sha512-c5gZOxocJKO/Zev2MEZInli+b+VNswDGuKHE6QtFgidhAJonwjh2kwj967RvWFaMMk62HlLJLZ+IGK2XsVy4Aw==
|
||||
"@docusaurus/plugin-content-docs@3.6.1":
|
||||
version "3.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.6.1.tgz#7c461b33ecc41e27fc02830bcde54378f68b2512"
|
||||
integrity sha512-Uq8kyn5DYCDmkUlB9sWChhWghS4lUFNiQU+RXcAXJ3qCVXsBpPsh6RF+npQG1N+j4wAbjydM1iLLJJzp+x3eMQ==
|
||||
dependencies:
|
||||
"@docusaurus/core" "3.6.0"
|
||||
"@docusaurus/logger" "3.6.0"
|
||||
"@docusaurus/mdx-loader" "3.6.0"
|
||||
"@docusaurus/module-type-aliases" "3.6.0"
|
||||
"@docusaurus/theme-common" "3.6.0"
|
||||
"@docusaurus/types" "3.6.0"
|
||||
"@docusaurus/utils" "3.6.0"
|
||||
"@docusaurus/utils-common" "3.6.0"
|
||||
"@docusaurus/utils-validation" "3.6.0"
|
||||
"@docusaurus/core" "3.6.1"
|
||||
"@docusaurus/logger" "3.6.1"
|
||||
"@docusaurus/mdx-loader" "3.6.1"
|
||||
"@docusaurus/module-type-aliases" "3.6.1"
|
||||
"@docusaurus/theme-common" "3.6.1"
|
||||
"@docusaurus/types" "3.6.1"
|
||||
"@docusaurus/utils" "3.6.1"
|
||||
"@docusaurus/utils-common" "3.6.1"
|
||||
"@docusaurus/utils-validation" "3.6.1"
|
||||
"@types/react-router-config" "^5.0.7"
|
||||
combine-promises "^1.1.0"
|
||||
fs-extra "^11.1.1"
|
||||
@ -3069,95 +3070,95 @@
|
||||
utility-types "^3.10.0"
|
||||
webpack "^5.88.1"
|
||||
|
||||
"@docusaurus/plugin-content-pages@3.6.0":
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.6.0.tgz#5dd284bf063baaba1e0305c90b1dd0d5acc7e466"
|
||||
integrity sha512-RKHhJrfkadHc7+tt1cP48NWifOrhkSRMPdXNYytzhoQrXlP6Ph+3tfQ4/n+nT0S3Y9+wwRxYqRqA380ZLt+QtQ==
|
||||
"@docusaurus/plugin-content-pages@3.6.1":
|
||||
version "3.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.6.1.tgz#7d3dcdcc49e3c31ed13dceab830ee7fd9a1c4658"
|
||||
integrity sha512-TZtL+2zq20gqGalzoIT2rEF1T4YCZ26jTvlCJXs78+incIajfdHtmdOq7rQW0oV7oqTjpGllbp788nY/vY9jgw==
|
||||
dependencies:
|
||||
"@docusaurus/core" "3.6.0"
|
||||
"@docusaurus/mdx-loader" "3.6.0"
|
||||
"@docusaurus/types" "3.6.0"
|
||||
"@docusaurus/utils" "3.6.0"
|
||||
"@docusaurus/utils-validation" "3.6.0"
|
||||
"@docusaurus/core" "3.6.1"
|
||||
"@docusaurus/mdx-loader" "3.6.1"
|
||||
"@docusaurus/types" "3.6.1"
|
||||
"@docusaurus/utils" "3.6.1"
|
||||
"@docusaurus/utils-validation" "3.6.1"
|
||||
fs-extra "^11.1.1"
|
||||
tslib "^2.6.0"
|
||||
webpack "^5.88.1"
|
||||
|
||||
"@docusaurus/plugin-debug@3.6.0":
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/plugin-debug/-/plugin-debug-3.6.0.tgz#0a6da9ba31a0acb176ae2762b4d6b96b1906c826"
|
||||
integrity sha512-o8T1Rl94COLdSlKvjYLQpRJQRU8WWZ8EX1B0yV0dQLNN8reyH7MQW+6z1ig4sQFfH3pnjPWVGHfuEjcib5m7Eg==
|
||||
"@docusaurus/plugin-debug@3.6.1":
|
||||
version "3.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/plugin-debug/-/plugin-debug-3.6.1.tgz#e73fca0307b864b000c98b7110009c6b4a3efc2b"
|
||||
integrity sha512-DeKPZtoVExDSYCbzoz7y5Dhc6+YPqRWfVGwEEUyKopSyQYefp0OV8hvASmbJCn2WyThRgspOUhog3FSEhz+agw==
|
||||
dependencies:
|
||||
"@docusaurus/core" "3.6.0"
|
||||
"@docusaurus/types" "3.6.0"
|
||||
"@docusaurus/utils" "3.6.0"
|
||||
"@docusaurus/core" "3.6.1"
|
||||
"@docusaurus/types" "3.6.1"
|
||||
"@docusaurus/utils" "3.6.1"
|
||||
fs-extra "^11.1.1"
|
||||
react-json-view-lite "^1.2.0"
|
||||
tslib "^2.6.0"
|
||||
|
||||
"@docusaurus/plugin-google-analytics@3.6.0":
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.6.0.tgz#9e8245eef1bee95e44ef2af92ce3e844a8e93e64"
|
||||
integrity sha512-kgRFbfpi6Hshj75YUztKyEMtI/kw0trPRwoTN4g+W1NK99R/vh8phTvhBTIMnDbetU79795LkwfG0rZ/ce6zWQ==
|
||||
"@docusaurus/plugin-google-analytics@3.6.1":
|
||||
version "3.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.6.1.tgz#f20027f75cd45830eefcd7a172ded8b15de0b516"
|
||||
integrity sha512-ZEoERiDHxSfhaEeT35ukQ892NzGHWiUvfxUsnPiRuGEhMoQlxMSp60shBuSZ1sUKuZlndoEl5qAXJg09Wls/Sg==
|
||||
dependencies:
|
||||
"@docusaurus/core" "3.6.0"
|
||||
"@docusaurus/types" "3.6.0"
|
||||
"@docusaurus/utils-validation" "3.6.0"
|
||||
"@docusaurus/core" "3.6.1"
|
||||
"@docusaurus/types" "3.6.1"
|
||||
"@docusaurus/utils-validation" "3.6.1"
|
||||
tslib "^2.6.0"
|
||||
|
||||
"@docusaurus/plugin-google-gtag@3.6.0":
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.6.0.tgz#bed8381fe3ab357d56a565f657e38d8ea6272703"
|
||||
integrity sha512-nqu4IfjaO4UX+dojHL2BxHRS+sKj31CIMWYo49huQ3wTET0Oc3u/WGTaKd3ShTPDhkgiRhTOSTPUwJWrU55nHg==
|
||||
"@docusaurus/plugin-google-gtag@3.6.1":
|
||||
version "3.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.6.1.tgz#db08bfcef319c494e5969c0d96d62bd8f43469db"
|
||||
integrity sha512-u/E9vXUsZxYaV6Brvfee8NiH/iR0cMml9P/ifz4EpH/Jfxdbw8rbCT0Nm/h7EFgEY48Uqkl5huSbIvFB9n8aTQ==
|
||||
dependencies:
|
||||
"@docusaurus/core" "3.6.0"
|
||||
"@docusaurus/types" "3.6.0"
|
||||
"@docusaurus/utils-validation" "3.6.0"
|
||||
"@docusaurus/core" "3.6.1"
|
||||
"@docusaurus/types" "3.6.1"
|
||||
"@docusaurus/utils-validation" "3.6.1"
|
||||
"@types/gtag.js" "^0.0.12"
|
||||
tslib "^2.6.0"
|
||||
|
||||
"@docusaurus/plugin-google-tag-manager@3.6.0":
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.6.0.tgz#326382de05888ea4317837be736eabd635adbc71"
|
||||
integrity sha512-OU6c5xI0nOVbEc9eImGvvsgNWe4vGm97t/W3aLHjWsHyNk3uwFNBQMHRvBUwAi9k/K3kyC5E7DWnc67REhdLOw==
|
||||
"@docusaurus/plugin-google-tag-manager@3.6.1":
|
||||
version "3.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.6.1.tgz#f3aa3cd0e7e6be793e5af3fe048a6ad12c3f0211"
|
||||
integrity sha512-By+NKkGYV8tSo8/RyS1OXikOtqsko5jJZ/uioJfBjsBGgSbiMJ+Y/HogFBke0mgSvf7NPGKZTbYm5+FJ8YUtPQ==
|
||||
dependencies:
|
||||
"@docusaurus/core" "3.6.0"
|
||||
"@docusaurus/types" "3.6.0"
|
||||
"@docusaurus/utils-validation" "3.6.0"
|
||||
"@docusaurus/core" "3.6.1"
|
||||
"@docusaurus/types" "3.6.1"
|
||||
"@docusaurus/utils-validation" "3.6.1"
|
||||
tslib "^2.6.0"
|
||||
|
||||
"@docusaurus/plugin-ideal-image@3.6.0":
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/plugin-ideal-image/-/plugin-ideal-image-3.6.0.tgz#41ffed294bd18ef7f9d4bf0d2d248a4bb890d62a"
|
||||
integrity sha512-6BaZU7mX+RH+lRFPm5nj3GGfAsjsJ1JHjp0Xjb4ilfte7L2IZkTl6MPpvAzyPC0qIUxfXRcJs4qd/HUE0xcTlw==
|
||||
"@docusaurus/plugin-ideal-image@3.6.1":
|
||||
version "3.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/plugin-ideal-image/-/plugin-ideal-image-3.6.1.tgz#3c0bb8e398ef0b7ea1ee313ee1e774de93f2b941"
|
||||
integrity sha512-hiGRPPlsM02aEOPlQc9rVnrckbVR6HswG7yDpZOtBEhw+ysXFsl/8gzAxFBL4ogKjN28WrlMCn/6IIkxY/EyOQ==
|
||||
dependencies:
|
||||
"@docusaurus/core" "3.6.0"
|
||||
"@docusaurus/lqip-loader" "3.6.0"
|
||||
"@docusaurus/core" "3.6.1"
|
||||
"@docusaurus/lqip-loader" "3.6.1"
|
||||
"@docusaurus/responsive-loader" "^1.7.0"
|
||||
"@docusaurus/theme-translations" "3.6.0"
|
||||
"@docusaurus/types" "3.6.0"
|
||||
"@docusaurus/utils-validation" "3.6.0"
|
||||
"@docusaurus/theme-translations" "3.6.1"
|
||||
"@docusaurus/types" "3.6.1"
|
||||
"@docusaurus/utils-validation" "3.6.1"
|
||||
"@slorber/react-ideal-image" "^0.0.12"
|
||||
react-waypoint "^10.3.0"
|
||||
sharp "^0.32.3"
|
||||
tslib "^2.6.0"
|
||||
webpack "^5.88.1"
|
||||
|
||||
"@docusaurus/plugin-pwa@3.6.0":
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/plugin-pwa/-/plugin-pwa-3.6.0.tgz#9851d1dd52bf8bf75f7d97e9f42cb6e29cacb68d"
|
||||
integrity sha512-IVUJIBeGwbIkrI8HgVkw3eonw23wq5EjPOioXzht4Dql1Bb13xF/SmO6Bj8NE2KNmlubOKRKwLy8gYpB3i8cmQ==
|
||||
"@docusaurus/plugin-pwa@3.6.1":
|
||||
version "3.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/plugin-pwa/-/plugin-pwa-3.6.1.tgz#541501c814d1b5d9681f8a55224e24b121ab7c75"
|
||||
integrity sha512-GsbpsgpAwdBpDpeVzk3UPNUQAc0oGU+0GL5s1LmFgqfpql5C7ZnkwD9FmW6lvieabQjC+Ga0d0zDqu20coqIRQ==
|
||||
dependencies:
|
||||
"@babel/core" "^7.25.9"
|
||||
"@babel/preset-env" "^7.25.9"
|
||||
"@docusaurus/bundler" "3.6.0"
|
||||
"@docusaurus/core" "3.6.0"
|
||||
"@docusaurus/logger" "3.6.0"
|
||||
"@docusaurus/theme-common" "3.6.0"
|
||||
"@docusaurus/theme-translations" "3.6.0"
|
||||
"@docusaurus/types" "3.6.0"
|
||||
"@docusaurus/utils" "3.6.0"
|
||||
"@docusaurus/utils-validation" "3.6.0"
|
||||
"@docusaurus/bundler" "3.6.1"
|
||||
"@docusaurus/core" "3.6.1"
|
||||
"@docusaurus/logger" "3.6.1"
|
||||
"@docusaurus/theme-common" "3.6.1"
|
||||
"@docusaurus/theme-translations" "3.6.1"
|
||||
"@docusaurus/types" "3.6.1"
|
||||
"@docusaurus/utils" "3.6.1"
|
||||
"@docusaurus/utils-validation" "3.6.1"
|
||||
babel-loader "^9.2.1"
|
||||
clsx "^2.0.0"
|
||||
core-js "^3.31.1"
|
||||
@ -3168,39 +3169,39 @@
|
||||
workbox-precaching "^7.0.0"
|
||||
workbox-window "^7.0.0"
|
||||
|
||||
"@docusaurus/plugin-sitemap@3.6.0":
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.6.0.tgz#c7c93f75f03391ca9071da48563fc4faa84966bc"
|
||||
integrity sha512-YB5XMdf9FjLhgbHY/cDbYhVxsgcpPIjxY9769HUgFOB7GVzItTLOR71W035R1BiR2CA5QAn3XOSg36WLRxlhQQ==
|
||||
"@docusaurus/plugin-sitemap@3.6.1":
|
||||
version "3.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.6.1.tgz#c842019a64d8dd12b64145115e60771d482db997"
|
||||
integrity sha512-i8R/GTKew4Cufb+7YQTwfPcNOhKTJzZ1VZ5OqQwI9c3pZK2TltQyhqKDVN94KCTbSSKvOYYytYfRAB2uPnH1/A==
|
||||
dependencies:
|
||||
"@docusaurus/core" "3.6.0"
|
||||
"@docusaurus/logger" "3.6.0"
|
||||
"@docusaurus/types" "3.6.0"
|
||||
"@docusaurus/utils" "3.6.0"
|
||||
"@docusaurus/utils-common" "3.6.0"
|
||||
"@docusaurus/utils-validation" "3.6.0"
|
||||
"@docusaurus/core" "3.6.1"
|
||||
"@docusaurus/logger" "3.6.1"
|
||||
"@docusaurus/types" "3.6.1"
|
||||
"@docusaurus/utils" "3.6.1"
|
||||
"@docusaurus/utils-common" "3.6.1"
|
||||
"@docusaurus/utils-validation" "3.6.1"
|
||||
fs-extra "^11.1.1"
|
||||
sitemap "^7.1.1"
|
||||
tslib "^2.6.0"
|
||||
|
||||
"@docusaurus/preset-classic@3.6.0":
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/preset-classic/-/preset-classic-3.6.0.tgz#71561f366a266be571022764eb8b9e5618f573eb"
|
||||
integrity sha512-kpGNdQzr/Dpm7o3b1iaQrz4DMDx3WIeBbl4V4P4maa2zAQkTdlaP4CMgA5oKrRrpqPLnQFsUM/b+qf2glhl2Tw==
|
||||
"@docusaurus/preset-classic@3.6.1":
|
||||
version "3.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/preset-classic/-/preset-classic-3.6.1.tgz#196540ca8495075d24eb724af3bf4c75d2412754"
|
||||
integrity sha512-b90Y1XRH9e+oa/E3NmiFEFOwgYUd+knFcZUy81nM3FJs038WbEA0T55NQsuPW0s7nOsCShQ7dVFyKxV+Wp31Nw==
|
||||
dependencies:
|
||||
"@docusaurus/core" "3.6.0"
|
||||
"@docusaurus/plugin-content-blog" "3.6.0"
|
||||
"@docusaurus/plugin-content-docs" "3.6.0"
|
||||
"@docusaurus/plugin-content-pages" "3.6.0"
|
||||
"@docusaurus/plugin-debug" "3.6.0"
|
||||
"@docusaurus/plugin-google-analytics" "3.6.0"
|
||||
"@docusaurus/plugin-google-gtag" "3.6.0"
|
||||
"@docusaurus/plugin-google-tag-manager" "3.6.0"
|
||||
"@docusaurus/plugin-sitemap" "3.6.0"
|
||||
"@docusaurus/theme-classic" "3.6.0"
|
||||
"@docusaurus/theme-common" "3.6.0"
|
||||
"@docusaurus/theme-search-algolia" "3.6.0"
|
||||
"@docusaurus/types" "3.6.0"
|
||||
"@docusaurus/core" "3.6.1"
|
||||
"@docusaurus/plugin-content-blog" "3.6.1"
|
||||
"@docusaurus/plugin-content-docs" "3.6.1"
|
||||
"@docusaurus/plugin-content-pages" "3.6.1"
|
||||
"@docusaurus/plugin-debug" "3.6.1"
|
||||
"@docusaurus/plugin-google-analytics" "3.6.1"
|
||||
"@docusaurus/plugin-google-gtag" "3.6.1"
|
||||
"@docusaurus/plugin-google-tag-manager" "3.6.1"
|
||||
"@docusaurus/plugin-sitemap" "3.6.1"
|
||||
"@docusaurus/theme-classic" "3.6.1"
|
||||
"@docusaurus/theme-common" "3.6.1"
|
||||
"@docusaurus/theme-search-algolia" "3.6.1"
|
||||
"@docusaurus/types" "3.6.1"
|
||||
|
||||
"@docusaurus/react-loadable@5.5.2":
|
||||
version "5.5.2"
|
||||
@ -3210,10 +3211,10 @@
|
||||
"@types/react" "*"
|
||||
prop-types "^15.6.2"
|
||||
|
||||
"@docusaurus/remark-plugin-npm2yarn@3.6.0":
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/remark-plugin-npm2yarn/-/remark-plugin-npm2yarn-3.6.0.tgz#b0e287c88ded88de576f1e2eb74d466062d73c35"
|
||||
integrity sha512-Imh0v68hFWSWlcE7qLlnZD9r4bQOzM6rcWTh6mPpfx2zHAai+so+SJmrMwZ1AJGfC08Y7Ch2Q/G4AThalXRVqQ==
|
||||
"@docusaurus/remark-plugin-npm2yarn@3.6.1":
|
||||
version "3.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/remark-plugin-npm2yarn/-/remark-plugin-npm2yarn-3.6.1.tgz#9098b41101fe99214ac837954ef6365c046f909f"
|
||||
integrity sha512-ve8xXfyB4oQwtYMgZoFxWWyp/aa3mobt4jLRjNHwRLQ6Jy7bMmFQ7uX99ExDttyGme2ABX4/vDNYfXDRdKm91Q==
|
||||
dependencies:
|
||||
mdast-util-mdx "^3.0.0"
|
||||
npm-to-yarn "^3.0.0"
|
||||
@ -3228,24 +3229,24 @@
|
||||
dependencies:
|
||||
loader-utils "^2.0.0"
|
||||
|
||||
"@docusaurus/theme-classic@3.6.0":
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/theme-classic/-/theme-classic-3.6.0.tgz#8f34b65c85f5082deb3633a893974d2eee309121"
|
||||
integrity sha512-sAXNfwPL6uRD+BuHuKXZfAXud7SS7IK/JdrPuzyQxdO1gJKzI5GFfe1ED1QoJDNWJWJ01JHE5rSnwYLEADc2rQ==
|
||||
"@docusaurus/theme-classic@3.6.1":
|
||||
version "3.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/theme-classic/-/theme-classic-3.6.1.tgz#dff4c7732b590e231dfb764e1d9a8acb5cf28954"
|
||||
integrity sha512-5lVUmIXk7zp+n9Ki2lYWrmhbd6mssOlKCnnDJvY4QDi3EgjRisIu5g4yKXoWTIbiqE7m7q/dS9cbeShEtfkKng==
|
||||
dependencies:
|
||||
"@docusaurus/core" "3.6.0"
|
||||
"@docusaurus/logger" "3.6.0"
|
||||
"@docusaurus/mdx-loader" "3.6.0"
|
||||
"@docusaurus/module-type-aliases" "3.6.0"
|
||||
"@docusaurus/plugin-content-blog" "3.6.0"
|
||||
"@docusaurus/plugin-content-docs" "3.6.0"
|
||||
"@docusaurus/plugin-content-pages" "3.6.0"
|
||||
"@docusaurus/theme-common" "3.6.0"
|
||||
"@docusaurus/theme-translations" "3.6.0"
|
||||
"@docusaurus/types" "3.6.0"
|
||||
"@docusaurus/utils" "3.6.0"
|
||||
"@docusaurus/utils-common" "3.6.0"
|
||||
"@docusaurus/utils-validation" "3.6.0"
|
||||
"@docusaurus/core" "3.6.1"
|
||||
"@docusaurus/logger" "3.6.1"
|
||||
"@docusaurus/mdx-loader" "3.6.1"
|
||||
"@docusaurus/module-type-aliases" "3.6.1"
|
||||
"@docusaurus/plugin-content-blog" "3.6.1"
|
||||
"@docusaurus/plugin-content-docs" "3.6.1"
|
||||
"@docusaurus/plugin-content-pages" "3.6.1"
|
||||
"@docusaurus/theme-common" "3.6.1"
|
||||
"@docusaurus/theme-translations" "3.6.1"
|
||||
"@docusaurus/types" "3.6.1"
|
||||
"@docusaurus/utils" "3.6.1"
|
||||
"@docusaurus/utils-common" "3.6.1"
|
||||
"@docusaurus/utils-validation" "3.6.1"
|
||||
"@mdx-js/react" "^3.0.0"
|
||||
clsx "^2.0.0"
|
||||
copy-text-to-clipboard "^3.2.0"
|
||||
@ -3260,15 +3261,15 @@
|
||||
tslib "^2.6.0"
|
||||
utility-types "^3.10.0"
|
||||
|
||||
"@docusaurus/theme-common@3.6.0":
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/theme-common/-/theme-common-3.6.0.tgz#9a061d278df76da0f70a9465cd0b7299c14d03d3"
|
||||
integrity sha512-frjlYE5sRs+GuPs4XXlp9aMLI2O4H5FPpznDAXBrCm+8EpWRiIb443ePMxM3IyMCQ5bwFlki0PI9C+r4apstnw==
|
||||
"@docusaurus/theme-common@3.6.1":
|
||||
version "3.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/theme-common/-/theme-common-3.6.1.tgz#d160516db9482ab19f7921d8a75093885d04d3de"
|
||||
integrity sha512-18iEYNpMvarGfq9gVRpGowSZD24vZ39Iz4acqaj64180i54V9el8tVnhNr/wRvrUm1FY30A1NHLqnMnDz4rYEQ==
|
||||
dependencies:
|
||||
"@docusaurus/mdx-loader" "3.6.0"
|
||||
"@docusaurus/module-type-aliases" "3.6.0"
|
||||
"@docusaurus/utils" "3.6.0"
|
||||
"@docusaurus/utils-common" "3.6.0"
|
||||
"@docusaurus/mdx-loader" "3.6.1"
|
||||
"@docusaurus/module-type-aliases" "3.6.1"
|
||||
"@docusaurus/utils" "3.6.1"
|
||||
"@docusaurus/utils-common" "3.6.1"
|
||||
"@types/history" "^4.7.11"
|
||||
"@types/react" "*"
|
||||
"@types/react-router-config" "*"
|
||||
@ -3278,34 +3279,34 @@
|
||||
tslib "^2.6.0"
|
||||
utility-types "^3.10.0"
|
||||
|
||||
"@docusaurus/theme-live-codeblock@3.6.0":
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/theme-live-codeblock/-/theme-live-codeblock-3.6.0.tgz#de670b60c9acfdf03feb79e32a3be0d90fe11647"
|
||||
integrity sha512-EphCTxJZgnEvgA1kdbr+R/cBu3fdawA2ooQji8EKPKg9i4Uex0xfFGhWja/0SaMKGqmfHRz9SY8I7j75O3cluw==
|
||||
"@docusaurus/theme-live-codeblock@3.6.1":
|
||||
version "3.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/theme-live-codeblock/-/theme-live-codeblock-3.6.1.tgz#748f2864df9ad2cdbb4f370b816ad1dc2d2bc175"
|
||||
integrity sha512-8GdnkwaNxb0dmRHGDlO+5QXdz9mrLni/wqai06LSGOTRv+GY3JC2Zov/KKkHZxx5MNFagqq01sGdn1TBBrS9jg==
|
||||
dependencies:
|
||||
"@docusaurus/core" "3.6.0"
|
||||
"@docusaurus/theme-common" "3.6.0"
|
||||
"@docusaurus/theme-translations" "3.6.0"
|
||||
"@docusaurus/utils-validation" "3.6.0"
|
||||
"@docusaurus/core" "3.6.1"
|
||||
"@docusaurus/theme-common" "3.6.1"
|
||||
"@docusaurus/theme-translations" "3.6.1"
|
||||
"@docusaurus/utils-validation" "3.6.1"
|
||||
"@philpl/buble" "^0.19.7"
|
||||
clsx "^2.0.0"
|
||||
fs-extra "^11.1.1"
|
||||
react-live "^4.1.6"
|
||||
tslib "^2.6.0"
|
||||
|
||||
"@docusaurus/theme-search-algolia@3.6.0":
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.6.0.tgz#47dcfca68f50163abce411dd9b181855a9ec9c83"
|
||||
integrity sha512-4IwRUkxjrisR8LXBHeE4d2btraWdMficbgiVL3UHvJURmyvgzMBZQP8KrK8rjdXeu8SuRxSmeV6NSVomRvdbEg==
|
||||
"@docusaurus/theme-search-algolia@3.6.1":
|
||||
version "3.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.6.1.tgz#a9cc9c9517a22459354703cf33d469e7263d3854"
|
||||
integrity sha512-BjmuiFRpQP1WEm8Mzu1Bb0Wdas6G65VHXDDNr7XTKgbstxalE6vuxt0ioXTDFS2YVep5748aVhKvnxR9gm2Liw==
|
||||
dependencies:
|
||||
"@docsearch/react" "^3.5.2"
|
||||
"@docusaurus/core" "3.6.0"
|
||||
"@docusaurus/logger" "3.6.0"
|
||||
"@docusaurus/plugin-content-docs" "3.6.0"
|
||||
"@docusaurus/theme-common" "3.6.0"
|
||||
"@docusaurus/theme-translations" "3.6.0"
|
||||
"@docusaurus/utils" "3.6.0"
|
||||
"@docusaurus/utils-validation" "3.6.0"
|
||||
"@docusaurus/core" "3.6.1"
|
||||
"@docusaurus/logger" "3.6.1"
|
||||
"@docusaurus/plugin-content-docs" "3.6.1"
|
||||
"@docusaurus/theme-common" "3.6.1"
|
||||
"@docusaurus/theme-translations" "3.6.1"
|
||||
"@docusaurus/utils" "3.6.1"
|
||||
"@docusaurus/utils-validation" "3.6.1"
|
||||
algoliasearch "^4.18.0"
|
||||
algoliasearch-helper "^3.13.3"
|
||||
clsx "^2.0.0"
|
||||
@ -3315,10 +3316,10 @@
|
||||
tslib "^2.6.0"
|
||||
utility-types "^3.10.0"
|
||||
|
||||
"@docusaurus/theme-translations@3.6.0":
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/theme-translations/-/theme-translations-3.6.0.tgz#93994e931f340c1712c81ac80dbab5750c24634f"
|
||||
integrity sha512-L555X8lWE3fv8VaF0Bc1VnAgi10UvRKFcvADHiYR7Gj37ItaWP5i7xLHsSw7fi/SHTXe5wfIeCFNqUYHyCOHAQ==
|
||||
"@docusaurus/theme-translations@3.6.1":
|
||||
version "3.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/theme-translations/-/theme-translations-3.6.1.tgz#d6bbb20141ca70f352201f2f412b6b8d988d86b4"
|
||||
integrity sha512-bNm5G6sueUezvyhsBegA1wwM38yW0BnqpZTE9KHO2yKnkERNMaV5x/yPJ/DNCOHjJtCcJ5Uz55g2AS75Go31xA==
|
||||
dependencies:
|
||||
fs-extra "^11.1.1"
|
||||
tslib "^2.6.0"
|
||||
@ -3342,10 +3343,10 @@
|
||||
webpack "^5.88.1"
|
||||
webpack-merge "^5.9.0"
|
||||
|
||||
"@docusaurus/types@3.6.0":
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/types/-/types-3.6.0.tgz#8fa82332a7c7b8093b5c55e1115f5854ce484978"
|
||||
integrity sha512-jADLgoZGWhAzThr+mRiyuFD4OUzt6jHnb7NRArRKorgxckqUBaPyFOau9hhbcSTHtU6ceyeWjN7FDt7uG2Hplw==
|
||||
"@docusaurus/types@3.6.1":
|
||||
version "3.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/types/-/types-3.6.1.tgz#0e55a0a51a3e55658b0845af83d5fe17c495978e"
|
||||
integrity sha512-hCB1hj9DYutVYBisnPNobz9SzEmCcf1EetJv09O49Cov3BqOkm+vnnjB3d957YJMtpLGQoKBeN/FF1DZ830JwQ==
|
||||
dependencies:
|
||||
"@mdx-js/mdx" "^3.0.0"
|
||||
"@types/history" "^4.7.11"
|
||||
@ -3357,34 +3358,36 @@
|
||||
webpack "^5.95.0"
|
||||
webpack-merge "^5.9.0"
|
||||
|
||||
"@docusaurus/utils-common@3.6.0":
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/utils-common/-/utils-common-3.6.0.tgz#11855ea503132bbcaba6ca4d351293ff10a75d34"
|
||||
integrity sha512-diUDNfbw33GaZMmKwdTckT2IBfVouXLXRD+zphH9ywswuaEIKqixvuf5g41H7MBBrlMsxhna3uTMoB4B/OPDcA==
|
||||
"@docusaurus/utils-common@3.6.1":
|
||||
version "3.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/utils-common/-/utils-common-3.6.1.tgz#994160470e6bd2c0eb771f2132883d21b3b6830f"
|
||||
integrity sha512-LX1qiTiC0aS8c92uZ+Wj2iNCNJyYZJIKY8/nZDKNMBfo759VYVS3RX3fKP3DznB+16sYp7++MyCz/T6fOGaRfw==
|
||||
dependencies:
|
||||
"@docusaurus/types" "3.6.1"
|
||||
tslib "^2.6.0"
|
||||
|
||||
"@docusaurus/utils-validation@3.6.0":
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/utils-validation/-/utils-validation-3.6.0.tgz#5557ca14fa64ac29e6f70e61006be721395ecde5"
|
||||
integrity sha512-CRHiKKJEKA0GFlfOf71JWHl7PtwOyX0+Zg9ep9NFEZv6Lcx3RJ9nhl7p8HRjPL6deyYceavM//BsfW4pCI4BtA==
|
||||
"@docusaurus/utils-validation@3.6.1":
|
||||
version "3.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/utils-validation/-/utils-validation-3.6.1.tgz#8e4b5bd8b71f55228543e3fda1301e9fb83df1c6"
|
||||
integrity sha512-+iMd6zRl5cJQm7nUP+7pSO/oAXsN79eHO34ME7l2YJt4GEAr70l5kkD58u2jEPpp+wSXT70c7x2A2lzJI1E8jw==
|
||||
dependencies:
|
||||
"@docusaurus/logger" "3.6.0"
|
||||
"@docusaurus/utils" "3.6.0"
|
||||
"@docusaurus/utils-common" "3.6.0"
|
||||
"@docusaurus/logger" "3.6.1"
|
||||
"@docusaurus/utils" "3.6.1"
|
||||
"@docusaurus/utils-common" "3.6.1"
|
||||
fs-extra "^11.2.0"
|
||||
joi "^17.9.2"
|
||||
js-yaml "^4.1.0"
|
||||
lodash "^4.17.21"
|
||||
tslib "^2.6.0"
|
||||
|
||||
"@docusaurus/utils@3.6.0":
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/utils/-/utils-3.6.0.tgz#192785da6fd62dfd83d6f1879c3aa45547f5df23"
|
||||
integrity sha512-VKczAutI4mptiAw/WcYEu5WeVhQ6Q1zdIUl64SGw9K++9lziH+Kt10Ee8l2dMpRkiUk6zzK20kMNlX2WCUwXYQ==
|
||||
"@docusaurus/utils@3.6.1":
|
||||
version "3.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@docusaurus/utils/-/utils-3.6.1.tgz#4e4f80be294671bfb83910352d3625878134bf48"
|
||||
integrity sha512-nS3WCvepwrnBEgSG5vQu40XG95lC9Jeh/odV5u5IhU1eQFEGDst9xBi6IK5yZdsGvbuaXBZLZtOqWYtuuFa/rQ==
|
||||
dependencies:
|
||||
"@docusaurus/logger" "3.6.0"
|
||||
"@docusaurus/utils-common" "3.6.0"
|
||||
"@docusaurus/logger" "3.6.1"
|
||||
"@docusaurus/types" "3.6.1"
|
||||
"@docusaurus/utils-common" "3.6.1"
|
||||
"@svgr/webpack" "^8.1.0"
|
||||
escape-string-regexp "^4.0.0"
|
||||
file-loader "^6.2.0"
|
||||
@ -4025,6 +4028,28 @@
|
||||
worker-loader "3.0.8"
|
||||
xmlbuilder2 "3.0.2"
|
||||
|
||||
"@kitware/vtk.js@32.1.1":
|
||||
version "32.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@kitware/vtk.js/-/vtk.js-32.1.1.tgz#20179cb5f65f33dea4626a948afe24eb16364f8a"
|
||||
integrity sha512-rrh+PvmjpMDCOsgr7B8ZVxnF75TXjUJOVleMO5QJFh7DP+31927l9DJA4WRiJU7mbpYuZGt8/vAojO5fCizUkA==
|
||||
dependencies:
|
||||
"@babel/runtime" "7.22.11"
|
||||
"@types/webxr" "^0.5.5"
|
||||
commander "9.2.0"
|
||||
d3-scale "4.0.2"
|
||||
fast-deep-equal "^3.1.3"
|
||||
fflate "0.7.3"
|
||||
gl-matrix "3.4.3"
|
||||
globalthis "1.0.3"
|
||||
seedrandom "3.0.5"
|
||||
shader-loader "1.3.1"
|
||||
shelljs "0.8.5"
|
||||
spark-md5 "3.0.2"
|
||||
stream-browserify "3.0.0"
|
||||
webworker-promise "0.5.0"
|
||||
worker-loader "3.0.8"
|
||||
xmlbuilder2 "3.0.2"
|
||||
|
||||
"@leichtgewicht/ip-codec@^2.0.1":
|
||||
version "2.0.5"
|
||||
resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz#4fc56c15c580b9adb7dc3c333a134e540b44bfb1"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user