@antimatter-audio/antimatter-ui 2.2.1 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -0
- package/dist/index.d.ts +12 -1
- package/dist/index.js +98 -45
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -46,6 +46,17 @@ NOTE: You will not see any _local_ changes you have made to this library yet. To
|
|
|
46
46
|
|
|
47
47
|
5. Run `npm run start` in **this project** to build your local changes.
|
|
48
48
|
|
|
49
|
+
6. If you don't see your changes, try running:
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
rm -rf node_modules
|
|
53
|
+
npm cache clean --force
|
|
54
|
+
npm install
|
|
55
|
+
npm run link-ui
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
in **antimatter-plugin-template**.
|
|
59
|
+
|
|
49
60
|
You should now see your local changes to these components at [http://localhost:3000](http://localhost:3000).
|
|
50
61
|
|
|
51
62
|
### Adding new components
|
package/dist/index.d.ts
CHANGED
|
@@ -141,8 +141,19 @@ interface KnobProps {
|
|
|
141
141
|
knobType?: KNOB_TYPE;
|
|
142
142
|
className?: string;
|
|
143
143
|
style?: object;
|
|
144
|
+
mockInitialScaledValue?: number;
|
|
145
|
+
mockProperties?: JuceSliderProperties;
|
|
144
146
|
}
|
|
145
|
-
|
|
147
|
+
interface JuceSliderProperties {
|
|
148
|
+
name?: string;
|
|
149
|
+
label?: string;
|
|
150
|
+
start: number;
|
|
151
|
+
end: number;
|
|
152
|
+
interval: number;
|
|
153
|
+
skew?: number;
|
|
154
|
+
numSteps?: number;
|
|
155
|
+
}
|
|
156
|
+
declare function Knob({ label, labelPosition, showValue, knobType, id, className, mockInitialScaledValue, mockProperties, }: React__default.PropsWithChildren<KnobProps>): React__default.JSX.Element;
|
|
146
157
|
declare namespace Knob {
|
|
147
158
|
var LABEL_POSITION: typeof POSITION;
|
|
148
159
|
var KNOB_TYPE: typeof KNOB_TYPE;
|
package/dist/index.js
CHANGED
|
@@ -476,6 +476,26 @@ var TextLabel = function(param) {
|
|
|
476
476
|
}, text ? text : children);
|
|
477
477
|
};
|
|
478
478
|
|
|
479
|
+
var clamp = function(val) {
|
|
480
|
+
var min = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : 0, max = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : 1;
|
|
481
|
+
return Math.max(min, Math.min(max, val));
|
|
482
|
+
};
|
|
483
|
+
// mocks the `normalisedToScaledValue` internal method from JUCE
|
|
484
|
+
// This will allow us to test the JS UI without needing access to the JUCE backend
|
|
485
|
+
function normalisedToScaledValue(param) {
|
|
486
|
+
var normalisedValue = param.normalisedValue, _param_skew = param.skew, skew = _param_skew === void 0 ? 1.0 : _param_skew, end = param.end, start = param.start;
|
|
487
|
+
return Math.pow(normalisedValue, 1 / skew) * (end - start) + start;
|
|
488
|
+
}
|
|
489
|
+
// mocks the `getNormalisedValue` method from JUCE
|
|
490
|
+
// This will allow us to test the JS UI without needing access to the JUCE backend
|
|
491
|
+
function getNormalisedValue(param) {
|
|
492
|
+
var scaledValue = param.scaledValue, start = param.start, end = param.end, _param_skew = param.skew, skew = _param_skew === void 0 ? 1.0 : _param_skew;
|
|
493
|
+
return Math.pow((scaledValue - start) / (end - start), skew);
|
|
494
|
+
}
|
|
495
|
+
var decimalToPercent = function(decimal) {
|
|
496
|
+
return Math.round(100 * (typeof decimal === 'string' ? parseFloat(decimal) : decimal));
|
|
497
|
+
};
|
|
498
|
+
|
|
479
499
|
function _array_like_to_array$1(arr, len) {
|
|
480
500
|
if (len == null || len > arr.length) len = arr.length;
|
|
481
501
|
for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
|
|
@@ -575,47 +595,87 @@ var KNOB_TYPE;
|
|
|
575
595
|
KNOB_TYPE["BIPOLAR"] = "BIPOLAR";
|
|
576
596
|
})(KNOB_TYPE || (KNOB_TYPE = {}));
|
|
577
597
|
function Knob(param) {
|
|
578
|
-
var label = param.label, _param_labelPosition = param.labelPosition, labelPosition = _param_labelPosition === void 0 ? POSITION.TOP : _param_labelPosition, _param_showValue = param.showValue, showValue = _param_showValue === void 0 ? true : _param_showValue, _param_knobType = param.knobType, knobType = _param_knobType === void 0 ? "STANDARD" : _param_knobType, id = param.id, className = param.className
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
598
|
+
var label = param.label, _param_labelPosition = param.labelPosition, labelPosition = _param_labelPosition === void 0 ? POSITION.TOP : _param_labelPosition, _param_showValue = param.showValue, showValue = _param_showValue === void 0 ? true : _param_showValue, _param_knobType = param.knobType, knobType = _param_knobType === void 0 ? "STANDARD" : _param_knobType, id = param.id, className = param.className, _param_mockInitialScaledValue = param.mockInitialScaledValue, mockInitialScaledValue = _param_mockInitialScaledValue === void 0 ? 0 : _param_mockInitialScaledValue, _param_mockProperties = param.// From https://github.com/juce-framework/JUCE/blob/51d11a2be6d5c97ccf12b4e5e827006e19f0555a/modules/juce_gui_extra/native/javascript/index.js#L135
|
|
599
|
+
mockProperties, mockProperties = _param_mockProperties === void 0 ? {
|
|
600
|
+
start: 0,
|
|
601
|
+
end: 100,
|
|
602
|
+
interval: 0.01,
|
|
603
|
+
skew: 1,
|
|
604
|
+
name: '',
|
|
605
|
+
label: '',
|
|
606
|
+
numSteps: 100
|
|
607
|
+
} : _param_mockProperties;
|
|
608
|
+
var knobState = Juce.getSliderState(id);
|
|
609
|
+
// if isLocalhost is true, the front end app is running outside of JUCE in a browser.
|
|
610
|
+
var isLocalhost = window.location.hostname === 'localhost';
|
|
611
|
+
// getNormalisedValue:
|
|
612
|
+
/**
|
|
613
|
+
* Returns the normalised value of the corresponding backend parameter. This value is always in the
|
|
614
|
+
* [0, 1] range (inclusive).
|
|
615
|
+
*
|
|
616
|
+
* The meaning of this range is the same as in the case of
|
|
617
|
+
* AudioProcessorParameter::getValue() (C++).
|
|
618
|
+
*/ // See https://github.com/juce-framework/JUCE/blob/51d11a2be6d5c97ccf12b4e5e827006e19f0555a/modules/juce_gui_extra/native/javascript/index.js#L230C1-L238C6
|
|
619
|
+
var _useState = _sliced_to_array$1(useState(0), 2), normalizedValue = _useState[0], setNormalizedValue = _useState[1];
|
|
620
|
+
// getScaledValue:
|
|
621
|
+
/**
|
|
622
|
+
* Returns the scaled value of the parameter. This corresponds to the return value of
|
|
623
|
+
* NormalisableRange::convertFrom0to1() (C++). This value will differ from a linear
|
|
624
|
+
* [0, 1] range if a non-default NormalisableRange was set for the parameter.
|
|
625
|
+
*/ var _useState1 = _sliced_to_array$1(useState(0), 2), scaledValue = _useState1[0], setScaledValue = _useState1[1];
|
|
626
|
+
var _useState2 = _sliced_to_array$1(useState(null), 2), properties = _useState2[0], setProperties = _useState2[1];
|
|
627
|
+
var handleChange = function(_, newValue) {
|
|
628
|
+
knobState === null || knobState === void 0 ? void 0 : knobState.setNormalisedValue(newValue);
|
|
629
|
+
// If the front end app is running in a browser, set the new value here.
|
|
630
|
+
// Otherwise, the value will come from JUCE.
|
|
631
|
+
if (isLocalhost) {
|
|
632
|
+
var newValueClamped = clamp(newValue);
|
|
633
|
+
setNormalizedValue(newValueClamped);
|
|
634
|
+
(mockProperties === null || mockProperties === void 0 ? void 0 : mockProperties.start) && (mockProperties === null || mockProperties === void 0 ? void 0 : mockProperties.end) && setScaledValue(normalisedToScaledValue({
|
|
635
|
+
normalisedValue: newValueClamped,
|
|
636
|
+
start: mockProperties === null || mockProperties === void 0 ? void 0 : mockProperties.start,
|
|
637
|
+
end: mockProperties === null || mockProperties === void 0 ? void 0 : mockProperties.end
|
|
638
|
+
}));
|
|
639
|
+
}
|
|
640
|
+
};
|
|
584
641
|
useEffect(function() {
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
642
|
+
{
|
|
643
|
+
if (isLocalhost) {
|
|
644
|
+
// This sets 'mockProperties' as the value for 'properties' if the app is running in a browser.
|
|
645
|
+
setProperties(mockProperties !== null && mockProperties !== void 0 ? mockProperties : null);
|
|
646
|
+
setNormalizedValue(getNormalisedValue({
|
|
647
|
+
scaledValue: mockInitialScaledValue,
|
|
648
|
+
start: mockProperties === null || mockProperties === void 0 ? void 0 : mockProperties.start,
|
|
649
|
+
end: mockProperties === null || mockProperties === void 0 ? void 0 : mockProperties.end
|
|
650
|
+
}));
|
|
651
|
+
setScaledValue(mockInitialScaledValue);
|
|
652
|
+
knobState.setNormalisedValue(mockInitialScaledValue);
|
|
653
|
+
return;
|
|
654
|
+
} else {
|
|
655
|
+
var valueListenerId = knobState.valueChangedEvent.addListener(function() {
|
|
656
|
+
setNormalizedValue(knobState.getNormalisedValue());
|
|
657
|
+
setScaledValue(knobState.getScaledValue());
|
|
658
|
+
});
|
|
659
|
+
var propertiesListenerId = knobState.propertiesChangedEvent.addListener(function() {
|
|
660
|
+
return setProperties(knobState.properties);
|
|
661
|
+
});
|
|
662
|
+
setProperties(knobState.properties);
|
|
663
|
+
setNormalizedValue(knobState.getNormalisedValue());
|
|
664
|
+
setScaledValue(knobState.getScaledValue());
|
|
665
|
+
return function cleanup() {
|
|
666
|
+
knobState.valueChangedEvent.removeListener(valueListenerId);
|
|
667
|
+
knobState.propertiesChangedEvent.removeListener(propertiesListenerId);
|
|
668
|
+
};
|
|
669
|
+
}
|
|
593
670
|
}
|
|
594
671
|
}, []);
|
|
595
|
-
useEffect(function() {
|
|
596
|
-
var knobState = Juce.getSliderState(id);
|
|
597
|
-
knobState.setNormalisedValue(Math.round(value) / 100);
|
|
598
|
-
}, [
|
|
599
|
-
value
|
|
600
|
-
]);
|
|
601
672
|
var bindDrag = useDrag(function(param) {
|
|
602
673
|
var down = param.down, delta = param.delta;
|
|
603
|
-
|
|
604
|
-
var newValue =
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
return max;
|
|
608
|
-
} else if (newValue <= min) {
|
|
609
|
-
return min;
|
|
610
|
-
} else {
|
|
611
|
-
return newValue;
|
|
612
|
-
}
|
|
613
|
-
} else {
|
|
614
|
-
return value;
|
|
615
|
-
}
|
|
616
|
-
});
|
|
674
|
+
if (down) {
|
|
675
|
+
var newValue = normalizedValue + delta[1] * ((properties === null || properties === void 0 ? void 0 : properties.interval) || 0.01) * -1;
|
|
676
|
+
handleChange(event, newValue);
|
|
677
|
+
}
|
|
617
678
|
}, {
|
|
618
|
-
delay: 1000,
|
|
619
679
|
preventDefault: true
|
|
620
680
|
});
|
|
621
681
|
return /*#__PURE__*/ React__default.createElement("div", {
|
|
@@ -637,24 +697,21 @@ function Knob(param) {
|
|
|
637
697
|
}), knobType === "BIPOLAR" && /*#__PURE__*/ React__default.createElement("div", {
|
|
638
698
|
className: "Knob-center-marker"
|
|
639
699
|
}), /*#__PURE__*/ React__default.createElement("div", _object_spread_props$1(_object_spread$1({
|
|
640
|
-
onPointerDown: function(e) {
|
|
641
|
-
return e.currentTarget.focus();
|
|
642
|
-
},
|
|
643
700
|
className: classnames('Knob', className)
|
|
644
701
|
}, bindDrag()), {
|
|
645
702
|
style: {
|
|
646
703
|
transform: knobType === "STANDARD" ? '' : ')',
|
|
647
704
|
touchAction: 'none'
|
|
648
705
|
}
|
|
649
|
-
}), /*#__PURE__*/ React__default.createElement("div", {
|
|
706
|
+
}), /*#__PURE__*/ React__default.createElement("ul", null, /*#__PURE__*/ React__default.createElement("li", null, properties === null || properties === void 0 ? void 0 : properties.start), /*#__PURE__*/ React__default.createElement("li", null, properties === null || properties === void 0 ? void 0 : properties.end), /*#__PURE__*/ React__default.createElement("li", null, normalizedValue)), /*#__PURE__*/ React__default.createElement("div", {
|
|
650
707
|
className: "Knob-inner",
|
|
651
708
|
style: {
|
|
652
|
-
rotate: knobType === "STANDARD" ?
|
|
709
|
+
rotate: "".concat(knobType === "STANDARD" ? normalizedValue : normalizedValue + 0.5, "turn")
|
|
653
710
|
}
|
|
654
711
|
}, /*#__PURE__*/ React__default.createElement("div", {
|
|
655
712
|
className: "Knob-marker"
|
|
656
713
|
}))), showValue && /*#__PURE__*/ React__default.createElement(TextLabel, {
|
|
657
|
-
text: "".concat(
|
|
714
|
+
text: "".concat(decimalToPercent(scaledValue)),
|
|
658
715
|
padding: [
|
|
659
716
|
SPACING.SMALL,
|
|
660
717
|
SPACING.NONE
|
|
@@ -667,10 +724,6 @@ Knob.KNOB_TYPE = KNOB_TYPE;
|
|
|
667
724
|
var css_248z$3 = ".Slider {\n height: 100%;\n width: 100%;\n display: flex;\n justify-content: center;\n}\n\n.track {\n background-color: #737373;\n}\n.horizontal .track {\n height: 12px;\n}\n.vertical .track {\n width: 12px;\n}\n\n.thumb {\n height: 12px;\n width: 12px;\n background-color: #404040;\n}";
|
|
668
725
|
styleInject(css_248z$3);
|
|
669
726
|
|
|
670
|
-
var decimalToPercent = function(decimal) {
|
|
671
|
-
return Math.ceil(decimal * 100);
|
|
672
|
-
};
|
|
673
|
-
|
|
674
727
|
function _array_like_to_array(arr, len) {
|
|
675
728
|
if (len == null || len > arr.length) len = arr.length;
|
|
676
729
|
for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../node_modules/style-inject/dist/style-inject.es.js"],"sourcesContent":["function styleInject(css, ref) {\n if ( ref === void 0 ) ref = {};\n var insertAt = ref.insertAt;\n\n if (!css || typeof document === 'undefined') { return; }\n\n var head = document.head || document.getElementsByTagName('head')[0];\n var style = document.createElement('style');\n style.type = 'text/css';\n\n if (insertAt === 'top') {\n if (head.firstChild) {\n head.insertBefore(style, head.firstChild);\n } else {\n head.appendChild(style);\n }\n } else {\n head.appendChild(style);\n }\n\n if (style.styleSheet) {\n style.styleSheet.cssText = css;\n } else {\n style.appendChild(document.createTextNode(css));\n }\n}\n\nexport default styleInject;\n"],"names":[],"mappings":";;;;;;;;AAAA,SAAS,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE;AAC/B,EAAE,KAAK,GAAG,KAAK,KAAK,CAAC,GAAG,GAAG,GAAG,EAAE,CAAC;AACjC,EAAE,IAAI,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC;AAC9B;AACA,EAAE,IAAI,CAAC,GAAG,IAAI,OAAO,QAAQ,KAAK,WAAW,EAAE,EAAE,OAAO,EAAE;AAC1D;AACA,EAAE,IAAI,IAAI,GAAG,QAAQ,CAAC,IAAI,IAAI,QAAQ,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;AACvE,EAAE,IAAI,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;AAC9C,EAAE,KAAK,CAAC,IAAI,GAAG,UAAU,CAAC;AAC1B;AACA,EAAE,IAAI,QAAQ,KAAK,KAAK,EAAE;AAC1B,IAAI,IAAI,IAAI,CAAC,UAAU,EAAE;AACzB,MAAM,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;AAChD,KAAK,MAAM;AACX,MAAM,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;AAC9B,KAAK;AACL,GAAG,MAAM;AACT,IAAI,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;AAC5B,GAAG;AACH;AACA,EAAE,IAAI,KAAK,CAAC,UAAU,EAAE;AACxB,IAAI,KAAK,CAAC,UAAU,CAAC,OAAO,GAAG,GAAG,CAAC;AACnC,GAAG,MAAM;AACT,IAAI,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC;AACpD,GAAG;AACH
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../node_modules/style-inject/dist/style-inject.es.js"],"sourcesContent":["function styleInject(css, ref) {\n if ( ref === void 0 ) ref = {};\n var insertAt = ref.insertAt;\n\n if (!css || typeof document === 'undefined') { return; }\n\n var head = document.head || document.getElementsByTagName('head')[0];\n var style = document.createElement('style');\n style.type = 'text/css';\n\n if (insertAt === 'top') {\n if (head.firstChild) {\n head.insertBefore(style, head.firstChild);\n } else {\n head.appendChild(style);\n }\n } else {\n head.appendChild(style);\n }\n\n if (style.styleSheet) {\n style.styleSheet.cssText = css;\n } else {\n style.appendChild(document.createTextNode(css));\n }\n}\n\nexport default styleInject;\n"],"names":[],"mappings":";;;;;;;;AAAA,SAAS,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE;AAC/B,EAAE,KAAK,GAAG,KAAK,KAAK,CAAC,GAAG,GAAG,GAAG,EAAE,CAAC;AACjC,EAAE,IAAI,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC;AAC9B;AACA,EAAE,IAAI,CAAC,GAAG,IAAI,OAAO,QAAQ,KAAK,WAAW,EAAE,EAAE,OAAO,EAAE;AAC1D;AACA,EAAE,IAAI,IAAI,GAAG,QAAQ,CAAC,IAAI,IAAI,QAAQ,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;AACvE,EAAE,IAAI,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;AAC9C,EAAE,KAAK,CAAC,IAAI,GAAG,UAAU,CAAC;AAC1B;AACA,EAAE,IAAI,QAAQ,KAAK,KAAK,EAAE;AAC1B,IAAI,IAAI,IAAI,CAAC,UAAU,EAAE;AACzB,MAAM,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;AAChD,KAAK,MAAM;AACX,MAAM,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;AAC9B,KAAK;AACL,GAAG,MAAM;AACT,IAAI,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;AAC5B,GAAG;AACH;AACA,EAAE,IAAI,KAAK,CAAC,UAAU,EAAE;AACxB,IAAI,KAAK,CAAC,UAAU,CAAC,OAAO,GAAG,GAAG,CAAC;AACnC,GAAG,MAAM;AACT,IAAI,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC;AACpD,GAAG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","x_google_ignoreList":[0]}
|