@icij/murmur-next 4.0.1 → 4.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/lib/components/AccordionStep.vue +53 -42
  2. package/lib/components/AccordionWrapper.vue +25 -24
  3. package/lib/components/ActiveTextTruncate.vue +44 -22
  4. package/lib/components/AdvancedLinkForm.vue +96 -46
  5. package/lib/components/Brand.vue +30 -23
  6. package/lib/components/BrandExpansion.vue +12 -3
  7. package/lib/components/ConfirmButton.vue +30 -26
  8. package/lib/components/ContentPlaceholder.vue +11 -7
  9. package/lib/components/CustomPagination.vue +50 -32
  10. package/lib/components/DigitsInput.vue +64 -60
  11. package/lib/components/DonateForm.vue +112 -83
  12. package/lib/components/EmbedForm.vue +37 -21
  13. package/lib/components/EmbeddableFooter.vue +14 -10
  14. package/lib/components/FollowUsPopover.vue +42 -40
  15. package/lib/components/GenericFooter.vue +98 -23
  16. package/lib/components/GenericHeader.vue +66 -29
  17. package/lib/components/HapticCopy.vue +41 -29
  18. package/lib/components/ImddbHeader.vue +113 -92
  19. package/lib/components/OrdinalLegend.vue +43 -20
  20. package/lib/components/RangePicker.vue +63 -42
  21. package/lib/components/ResponsiveIframe.vue +9 -2
  22. package/lib/components/ScaleLegend.vue +56 -18
  23. package/lib/components/SecretInput.vue +7 -8
  24. package/lib/components/SelectableDropdown.vue +120 -74
  25. package/lib/components/SharingOptions.vue +93 -36
  26. package/lib/components/SharingOptionsLink.vue +11 -5
  27. package/lib/components/SignUpForm.vue +44 -23
  28. package/lib/components/SlideUpDown.vue +7 -2
  29. package/lib/components/TexturedDeck.vue +24 -14
  30. package/lib/components/TinyPagination.vue +35 -22
  31. package/lib/composables/chart.ts +174 -157
  32. package/lib/composables/resizeObserver.ts +29 -29
  33. package/lib/composables/sendEmail.ts +53 -42
  34. package/lib/config.default.ts +17 -10
  35. package/lib/config.ts +34 -27
  36. package/lib/datavisualisations/BarChart.vue +48 -42
  37. package/lib/datavisualisations/ColumnChart.vue +133 -89
  38. package/lib/datavisualisations/LineChart.vue +79 -57
  39. package/lib/datavisualisations/StackedBarChart.vue +116 -68
  40. package/lib/datavisualisations/StackedColumnChart.vue +196 -115
  41. package/lib/enums.ts +25 -15
  42. package/lib/i18n.ts +3 -3
  43. package/lib/keys.ts +2 -2
  44. package/lib/main.ts +14 -10
  45. package/lib/maps/ChoroplethMap.vue +299 -160
  46. package/lib/maps/ChoroplethMapAnnotation.vue +29 -18
  47. package/lib/maps/SymbolMap.vue +194 -123
  48. package/lib/shims-bootstrap-vue.d.ts +1 -1
  49. package/lib/shims-vue.d.ts +3 -3
  50. package/lib/styles/functions.scss +10 -6
  51. package/lib/styles/lib.scss +2 -4
  52. package/lib/styles/mixins.scss +8 -8
  53. package/lib/styles/utilities.scss +1 -1
  54. package/lib/styles/variables.scss +24 -18
  55. package/lib/types.ts +26 -10
  56. package/lib/utils/animation.ts +4 -4
  57. package/lib/utils/assets.ts +31 -28
  58. package/lib/utils/clipboard.ts +16 -10
  59. package/lib/utils/iframe-resizer.ts +18 -13
  60. package/lib/utils/placeholder.ts +54 -23
  61. package/lib/utils/placeholderTypes.ts +3 -3
  62. package/package.json +7 -2
@@ -4,179 +4,196 @@ import isObject from 'lodash/isObject'
4
4
  import isString from 'lodash/isString'
5
5
  import max from 'lodash/max'
6
6
  import some from 'lodash/some'
7
- import {ComponentPublicInstance, computed, onMounted, ref, watch} from 'vue'
8
- import {isUrl} from '@/utils/strings'
9
- import { Ref, SetupContext} from "@vue/runtime-core";
10
- import useResizeObserver from "@/composables/resizeObserver";
7
+ import { ComponentPublicInstance, computed, onMounted, ref, watch } from 'vue'
8
+ import { isUrl } from '@/utils/strings'
9
+ import { Ref, SetupContext } from '@vue/runtime-core'
10
+ import useResizeObserver from '@/composables/resizeObserver'
11
11
  import { watchEffect } from 'vue'
12
12
 
13
-
14
- type ChartContext<T extends string[]> = SetupContext<[...T, ...string[]]>;
15
- type ChartEmit = Pick<ChartContext<["resized", "loaded"]>, 'emit'>
13
+ type ChartContext<T extends string[]> = SetupContext<[...T, ...string[]]>
14
+ type ChartEmit = Pick<ChartContext<['resized', 'loaded']>, 'emit'>
16
15
  type ChartProps = {
17
- chartHeightRatio: { type: NumberConstructor },
18
- data: {
19
- default: () => any[] | string,
20
- validator(value: string): boolean,
21
- type: (ArrayConstructor | StringConstructor | ObjectConstructor)[]
22
- },
23
- dataUrlType: { default: string, validator(value: string): boolean, type: StringConstructor },
24
- socialMode: { type: BooleanConstructor },
25
- socialModeRatio:
26
- { default: number, type: NumberConstructor }
27
- };
16
+ chartHeightRatio: { type: NumberConstructor }
17
+ data: {
18
+ default: () => any[] | string
19
+ validator(value: string): boolean
20
+ type: (ArrayConstructor | StringConstructor | ObjectConstructor)[]
21
+ }
22
+ dataUrlType: {
23
+ default: string
24
+ validator(value: string): boolean
25
+ type: StringConstructor
26
+ }
27
+ socialMode: { type: BooleanConstructor }
28
+ socialModeRatio: { default: number; type: NumberConstructor }
29
+ }
28
30
 
29
31
  export function getChartProps(props: any): ChartProps {
30
- return {
31
- chartHeightRatio: props.chartHeightRatio,
32
- data: props.data,
33
- dataUrlType: props.dataUrlType,
34
- socialMode: props.socialMode,
35
- socialModeRatio: props.socialModeRatio,
36
- }
32
+ return {
33
+ chartHeightRatio: props.chartHeightRatio,
34
+ data: props.data,
35
+ dataUrlType: props.dataUrlType,
36
+ socialMode: props.socialMode,
37
+ socialModeRatio: props.socialModeRatio
38
+ }
37
39
  }
38
40
 
39
41
  export const chartProps = (): ChartProps => ({
40
- data: {
41
- type: [Array, String, Object],
42
- default: () => [],
43
- validator(value: string) {
44
- return isObject(value) || (isString(value) && isUrl(value))
45
- }
46
- },
47
- /**
48
- * Format of the data to load.
49
- */
50
- dataUrlType: {
51
- type: String,
52
- default: 'json',
53
- validator(value: string) {
54
- return ['json', 'csv', 'tsv'].indexOf(value) > -1
55
- }
56
- },
57
- /**
58
- * When applicable, default chart's height ratio
59
- */
60
- chartHeightRatio: {
61
- type: Number
62
- },
63
- /**
64
- * If true, the chart will be display on social mode
65
- */
66
- socialMode: {
67
- type: Boolean
68
- },
69
- /**
70
- * Ratio to use in social mode
71
- */
72
- socialModeRatio: {
73
- type: Number,
74
- default: 5 / 4
42
+ data: {
43
+ type: [Array, String, Object],
44
+ default: () => [],
45
+ validator(value: string) {
46
+ return isObject(value) || (isString(value) && isUrl(value))
47
+ }
48
+ },
49
+ /**
50
+ * Format of the data to load.
51
+ */
52
+ dataUrlType: {
53
+ type: String,
54
+ default: 'json',
55
+ validator(value: string) {
56
+ return ['json', 'csv', 'tsv'].indexOf(value) > -1
75
57
  }
58
+ },
59
+ /**
60
+ * When applicable, default chart's height ratio
61
+ */
62
+ chartHeightRatio: {
63
+ type: Number
64
+ },
65
+ /**
66
+ * If true, the chart will be display on social mode
67
+ */
68
+ socialMode: {
69
+ type: Boolean
70
+ },
71
+ /**
72
+ * Ratio to use in social mode
73
+ */
74
+ socialModeRatio: {
75
+ type: Number,
76
+ default: 5 / 4
77
+ }
76
78
  })
77
- export const chartEmits = ["resized", "loaded"]
78
- type Chart = {
79
- dataHasHighlights: any;
80
- loadedData: any;
81
- xAxisYearFormat: (year: (number | string)) => number | string;
82
- elementsMaxBBox: ({selector, defaultWidth, defaultHeight}?: {
83
- selector?: any;
84
- defaultWidth?: any;
85
- defaultHeight?: any
86
- }) => ({ width: any; height: any });
87
- d3Formatter: any;
88
- baseHeightRatio: any
79
+ export const chartEmits = ['resized', 'loaded']
80
+ type Chart = {
81
+ dataHasHighlights: any
82
+ loadedData: any
83
+ xAxisYearFormat: (year: number | string) => number | string
84
+ elementsMaxBBox: ({
85
+ selector,
86
+ defaultWidth,
87
+ defaultHeight
88
+ }?: {
89
+ selector?: any
90
+ defaultWidth?: any
91
+ defaultHeight?: any
92
+ }) => { width: any; height: any }
93
+ d3Formatter: any
94
+ baseHeightRatio: any
89
95
  }
90
- export function useChart(resizableRef: Ref<ComponentPublicInstance<HTMLElement> | null>, props: ChartProps, {emit}: ChartEmit, isLoaded:Ref<boolean>, onResized?:Function, afterLoaded?:()=>Promise<any>): Chart {
91
- const { resizeRef , resizeState } = useResizeObserver(resizableRef)
92
- const loadedData = ref([])
93
-
94
- onMounted(async () => {
95
- await document.fonts?.ready
96
-
97
- watchEffect(async ()=>{
98
- if(!isLoaded.value){
99
-
100
- if (isString(props.data)) {
101
- // @ts-ignore
102
- loadedData.value = await d3[props.dataUrlType](props.data)
103
- } else {
104
- loadedData.value = props.data as unknown as []
105
- }
106
-
107
- if(afterLoaded){
108
- await afterLoaded()
109
- }
110
- isLoaded.value = true
111
- emit('loaded')
112
- }
113
-
114
- if(isLoaded.value && onResized){
115
- onResized()
116
- emit('resized')
117
- }
118
- })
119
-
120
-
121
- })
122
- function elementsMaxBBox({selector = 'text', defaultWidth = null, defaultHeight = null} = {}) {
123
-
124
- const elements = isLoaded.value? resizeRef.value?.querySelectorAll(selector) : []
125
- if (elements.length == 0) {
126
- return {width: defaultWidth, height: defaultHeight}
96
+ export function useChart(
97
+ resizableRef: Ref<ComponentPublicInstance<HTMLElement> | null>,
98
+ props: ChartProps,
99
+ { emit }: ChartEmit,
100
+ isLoaded: Ref<boolean>,
101
+ onResized?: Function,
102
+ afterLoaded?: () => Promise<any>
103
+ ): Chart {
104
+ const { resizeRef, resizeState } = useResizeObserver(resizableRef)
105
+ const loadedData = ref([])
106
+
107
+ onMounted(async () => {
108
+ await document.fonts?.ready
109
+
110
+ watchEffect(async () => {
111
+ if (!isLoaded.value) {
112
+ if (isString(props.data)) {
113
+ // @ts-ignore
114
+ loadedData.value = await d3[props.dataUrlType](props.data)
115
+ } else {
116
+ loadedData.value = props.data as unknown as []
127
117
  }
128
- const width = max(
129
- [...elements].map((l) => {
130
- return l.getBBox ? l.getBBox().width : defaultWidth
131
- })
132
- )
133
- const height = max(
134
- [...elements].map((l) => {
135
- return l.getBBox ? l.getBBox().height : defaultHeight
136
- })
137
- )
138
- return {width, height}
139
- }
140
118
 
141
- function xAxisYearFormat(year: number | string) {
142
- // previously using narrowWidth but it is automatically updated through resizeObserver state reactivity
143
- return resizeState.narrowWidth ? '’' + String(year).slice(2, 4) : year
119
+ if (afterLoaded) {
120
+ await afterLoaded()
121
+ }
122
+ isLoaded.value = true
123
+ emit('loaded')
124
+ }
125
+
126
+ if (isLoaded.value && onResized) {
127
+ onResized()
128
+ emit('resized')
129
+ }
130
+ })
131
+ })
132
+ function elementsMaxBBox({
133
+ selector = 'text',
134
+ defaultWidth = null,
135
+ defaultHeight = null
136
+ } = {}) {
137
+ const elements = isLoaded.value
138
+ ? resizeRef.value?.querySelectorAll(selector)
139
+ : []
140
+ if (elements.length == 0) {
141
+ return { width: defaultWidth, height: defaultHeight }
144
142
  }
145
- function highlighted(datum: { highlight: boolean }) {
146
- return datum.highlight
143
+ const width = max(
144
+ [...elements].map((l) => {
145
+ return l.getBBox ? l.getBBox().width : defaultWidth
146
+ })
147
+ )
148
+ const height = max(
149
+ [...elements].map((l) => {
150
+ return l.getBBox ? l.getBBox().height : defaultHeight
151
+ })
152
+ )
153
+ return { width, height }
154
+ }
155
+
156
+ function xAxisYearFormat(year: number | string) {
157
+ // previously using narrowWidth but it is automatically updated through resizeObserver state reactivity
158
+ return resizeState.narrowWidth ? '’' + String(year).slice(2, 4) : year
159
+ }
160
+ function highlighted(datum: { highlight: boolean }) {
161
+ return datum.highlight
162
+ }
163
+ function d3Formatter(value: any, formatter: any) {
164
+ if (isFunction(formatter)) {
165
+ return formatter(value)
166
+ } else if (isString(formatter)) {
167
+ return d3.format(formatter)(value)
147
168
  }
148
- function d3Formatter(value:any,formatter:any) {
149
- if (isFunction(formatter)) {
150
- return formatter(value)
151
- } else if (isString(formatter)) {
152
- return d3.format(formatter)(value)
153
- }
154
- return value
169
+ return value
170
+ }
171
+ const baseHeightRatio = computed(() => {
172
+ return (
173
+ props.chartHeightRatio ||
174
+ (props.socialMode ? props.socialModeRatio : 9 / 16)
175
+ )
176
+ })
177
+ const dataHasHighlights = computed(() => {
178
+ if (Array.isArray(props.data)) {
179
+ return some(props.data, highlighted)
155
180
  }
156
- const baseHeightRatio = computed(() => {
157
- return props.chartHeightRatio || (props.socialMode ? props.socialModeRatio : 9 / 16)
158
- })
159
- const dataHasHighlights = computed(() => {
160
- if (Array.isArray(props.data)) {
161
- return some(props.data, highlighted)
162
- }
163
- return false
164
- })
165
-
166
- watch(resizeState.dimensions, () => {
167
- if(isLoaded.value && onResized){
168
- onResized()
169
- emit('resized')
170
- }
171
- })
172
-
181
+ return false
182
+ })
173
183
 
174
- return {
175
- loadedData,
176
- elementsMaxBBox,
177
- xAxisYearFormat,
178
- d3Formatter,
179
- baseHeightRatio,
180
- dataHasHighlights,
184
+ watch(resizeState.dimensions, () => {
185
+ if (isLoaded.value && onResized) {
186
+ onResized()
187
+ emit('resized')
181
188
  }
189
+ })
190
+
191
+ return {
192
+ loadedData,
193
+ elementsMaxBBox,
194
+ xAxisYearFormat,
195
+ d3Formatter,
196
+ baseHeightRatio,
197
+ dataHasHighlights
198
+ }
182
199
  }
@@ -1,37 +1,37 @@
1
- import { ref, reactive, onMounted, onBeforeUnmount } from "vue";
2
- import { Ref,nextTick } from "vue";
1
+ import { ref, reactive, onMounted, onBeforeUnmount } from 'vue'
2
+ import { Ref, nextTick } from 'vue'
3
3
  import ResizeObserver from 'resize-observer-polyfill'
4
4
 
5
- export const useResizeObserver = (resizableRef?:Ref) => {
6
- const resizeRef:Ref<HTMLElement> = resizableRef ?? ref();
7
- const resizeState = reactive({
8
- dimensions: {} as DOMRect,
9
- offsetWidth: 540,
10
- narrowWidth: false
11
- });
5
+ export const useResizeObserver = (resizableRef?: Ref) => {
6
+ const resizeRef: Ref<HTMLElement> = resizableRef ?? ref()
7
+ const resizeState = reactive({
8
+ dimensions: {} as DOMRect,
9
+ offsetWidth: 540,
10
+ narrowWidth: false
11
+ })
12
12
 
13
- const observer = new ResizeObserver(entries => {
14
- entries.forEach(entry => {
15
- resizeState.dimensions = entry.contentRect
16
- resizeState.offsetWidth = (entry.target as HTMLElement).offsetWidth
17
- resizeState.narrowWidth = (resizeState.offsetWidth ?? 540) < 540
18
- });
19
- });
13
+ const observer = new ResizeObserver((entries) => {
14
+ entries.forEach((entry) => {
15
+ resizeState.dimensions = entry.contentRect
16
+ resizeState.offsetWidth = (entry.target as HTMLElement).offsetWidth
17
+ resizeState.narrowWidth = (resizeState.offsetWidth ?? 540) < 540
18
+ })
19
+ })
20
20
 
21
- onMounted(async () => {
22
- // set initial dimensions right before observing: Element.getBoundingClientRect()
23
- resizeState.dimensions = resizeRef.value.getBoundingClientRect();
24
- resizeState.offsetWidth = resizeRef.value.offsetWidth
25
- resizeState.narrowWidth = false // TODO CD: old default is false but maybe this would work (resizeState.offsetWidth ?? 540) < 540 but would be often true
21
+ onMounted(async () => {
22
+ // set initial dimensions right before observing: Element.getBoundingClientRect()
23
+ resizeState.dimensions = resizeRef.value.getBoundingClientRect()
24
+ resizeState.offsetWidth = resizeRef.value.offsetWidth
25
+ resizeState.narrowWidth = false // TODO CD: old default is false but maybe this would work (resizeState.offsetWidth ?? 540) < 540 but would be often true
26
26
 
27
- observer.observe(resizeRef.value);
28
- });
27
+ observer.observe(resizeRef.value)
28
+ })
29
29
 
30
- onBeforeUnmount(() => {
31
- observer.unobserve(resizeRef.value);
32
- });
30
+ onBeforeUnmount(() => {
31
+ observer.unobserve(resizeRef.value)
32
+ })
33
33
 
34
- return { resizeState, resizeRef };
35
- };
34
+ return { resizeState, resizeRef }
35
+ }
36
36
 
37
- export default useResizeObserver;
37
+ export default useResizeObserver
@@ -1,50 +1,61 @@
1
- import jsonp from "jsonp";
2
- import {computed, MaybeRefOrGetter, toValue} from "vue";
3
- import flatten from "lodash/flatten";
4
- import castArray from "lodash/castArray";
5
- import {Ref} from "react";
1
+ import jsonp from 'jsonp'
2
+ import { computed, MaybeRefOrGetter, toValue } from 'vue'
3
+ import flatten from 'lodash/flatten'
4
+ import castArray from 'lodash/castArray'
5
+ import { Ref } from 'react'
6
6
 
7
7
  type FormDataResult = { result: string; msg: string }
8
8
  // by convention, composable function names start with "use"
9
- export function useSendEmail(email:MaybeRefOrGetter<string>,action?:string,emailField?:string, tracker?:string, referrer?:string|null,defaultGroups?:string[]|string,) {
10
- const emailValue = toValue(email)
11
-
12
- const groups = computed(()=> {
13
- return flatten(castArray(defaultGroups).map((g) => g.split(',')))
14
- })
15
-
16
- const urlFromAction = computed(()=> {
17
- return action?.replace('/post?', '/post-json?').concat('&c=?')
18
- })
19
- const parentReferrer = computed(()=> {
20
- if (referrer) {
21
- return referrer
22
- }
23
- return window.location !== window.parent.location ? document.referrer : document.location.href
24
- })
9
+ export function useSendEmail(
10
+ email: MaybeRefOrGetter<string>,
11
+ action?: string,
12
+ emailField?: string,
13
+ tracker?: string,
14
+ referrer?: string | null,
15
+ defaultGroups?: string[] | string
16
+ ) {
17
+ const emailValue = toValue(email)
18
+
19
+ const groups = computed(() => {
20
+ return flatten(castArray(defaultGroups).map((g) => g.split(',')))
21
+ })
22
+
23
+ const urlFromAction = computed(() => {
24
+ return action?.replace('/post?', '/post-json?').concat('&c=?')
25
+ })
26
+ const parentReferrer = computed(() => {
27
+ if (referrer) {
28
+ return referrer
29
+ }
30
+ return window.location !== window.parent.location
31
+ ? document.referrer
32
+ : document.location.href
33
+ })
34
+
35
+ const submitUrl = computed(() => {
36
+ if (typeof urlFromAction.value == 'undefined' || !tracker || !emailField) {
37
+ throw new Error('Missing url Info')
38
+ }
25
39
 
26
- const submitUrl = computed(()=> {
27
- if(typeof urlFromAction.value == 'undefined' || !tracker || !emailField){
28
- throw new Error("Missing url Info")
40
+ const url = new URL(urlFromAction.value)
41
+ url.searchParams.set('SIGNUP', tracker)
42
+ url.searchParams.set('MMERGE24', parentReferrer.value)
43
+ url.searchParams.set(emailField, emailValue)
44
+ groups.value.map((group) => url.searchParams.set(group, '1'))
45
+
46
+ return url.href
47
+ })
48
+ function send() {
49
+ return new Promise((resolve, reject) => {
50
+ jsonp(
51
+ submitUrl.value,
52
+ { param: 'c' },
53
+ (err: any, data: FormDataResult) => {
54
+ return err ? reject(err) : resolve(data)
29
55
  }
30
-
31
- const url = new URL(urlFromAction.value)
32
- url.searchParams.set('SIGNUP', tracker)
33
- url.searchParams.set('MMERGE24', parentReferrer.value)
34
- url.searchParams.set(emailField, emailValue)
35
- groups.value.map((group) => url.searchParams.set(group, '1'))
36
-
37
- return url.href
56
+ )
38
57
  })
39
- function send() {
40
- return new Promise((resolve, reject) => {
41
- jsonp(submitUrl.value, { param: 'c' }, (err: any, data: FormDataResult) => {
42
- return err ? reject(err) : resolve(data)
43
- })
44
- })
45
- }
46
-
58
+ }
47
59
 
48
- return {send}
60
+ return { send }
49
61
  }
50
-
@@ -1,20 +1,24 @@
1
1
  export default {
2
2
  'imddb-header.dropdown.items': [
3
- { label: 'Graphics', href: "#/" },
4
- { label: 'Overview', href: "#/" },
5
- { label: 'Visual overview', href: "#/" },
6
- { label: 'Backgrounder', href: "#/" },
7
- { label: 'About this project', href: "#/", active: true }
3
+ { label: 'Graphics', href: '#/' },
4
+ { label: 'Overview', href: '#/' },
5
+ { label: 'Visual overview', href: '#/' },
6
+ { label: 'Backgrounder', href: '#/' },
7
+ { label: 'About this project', href: '#/', active: true }
8
8
  ],
9
9
  'project.name': 'Secret Papers',
10
10
  'app.name': 'Awesome App',
11
11
  'app.home': './',
12
12
  'app.donate-url': 'https://www.icij.org/donate/',
13
- 'contact-email':'contact@icij.org',
13
+ 'contact-email': 'contact@icij.org',
14
14
  'content-placeholder.rows': [
15
15
  {
16
16
  height: '1em',
17
- boxes: [[0, '50%'], ['5%', '30%'], ['5%', '10%']]
17
+ boxes: [
18
+ [0, '50%'],
19
+ ['5%', '30%'],
20
+ ['5%', '10%']
21
+ ]
18
22
  }
19
23
  ],
20
24
  'donate-form.tracker': null,
@@ -24,10 +28,13 @@ export default {
24
28
  'sharing-options.media': null,
25
29
  'sharing-options.twitter-user': 'ICIJorg',
26
30
  'signup-form.tracker': 'EXTERNAL',
27
- 'signup-form.action': 'https://icij.us15.list-manage.com/subscribe/post?u=0d48a33b1c24d257734cc2a79&id=992ecfdbb2',
31
+ 'signup-form.action':
32
+ 'https://icij.us15.list-manage.com/subscribe/post?u=0d48a33b1c24d257734cc2a79&id=992ecfdbb2',
28
33
  'signup-form.email-field': 'EMAIL',
29
34
  'signup-form.default-groups': ['group[9][1]'],
30
35
  'textured-deck.background-base-url': 'https://icij.github.io/murmur',
31
- 'map.topojson.world-countries-sans-antarctica': 'https://icij.github.io/murmur/assets/topojson/world-countries-sans-antarctica.json',
32
- 'map.topojson.france-departements': 'https://icij.github.io/murmur/assets/topojson/france-departements.json'
36
+ 'map.topojson.world-countries-sans-antarctica':
37
+ 'https://icij.github.io/murmur/assets/topojson/world-countries-sans-antarctica.json',
38
+ 'map.topojson.france-departements':
39
+ 'https://icij.github.io/murmur/assets/topojson/france-departements.json'
33
40
  }