'use strict';
+import DIGITS from './DIGITS';
import DynamicField from './DynamicField.react';
import React from 'react';
import type Value from './Field.react';
import Field from './Field.react';
import Label from './Label.react';
import Size from './Size.react';
+import convert from './convert';
import './App.css';
+const SERIALIZATION_BASE = DIGITS.length;
+
+function getInitialValue() {
+ // Extract value from URL fragment, if present.
+ const value = window.location.hash.replace(/^#/, '');
+ const validator = new RegExp(`^[${DIGITS}]+$`);
+ if (!validator.test(value)) {
+ return null;
+ } else {
+ return {
+ base: SERIALIZATION_BASE,
+ value,
+ };
+ }
+}
+
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
- value: null,
+ value: getInitialValue(),
};
}
_onValueChange = (value: Value) => {
this.setState({value});
+ window.history.replaceState(
+ {},
+ '',
+ '#' + convert(value.value, value.base, SERIALIZATION_BASE)
+ );
}
componentDidMount() {
--- /dev/null
+/**
+ * Copyright 2015-present Greg Hurrell. All rights reserved.
+ * Licensed under the terms of the MIT license.
+ *
+ * @flow
+ */
+
+'use strict';
+
+const DIGITS = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
+
+export default DIGITS;
'use strict';
+import DIGITS from './DIGITS';
import React from 'react';
import convert from './convert';
import cx from 'classnames';
value: React.PropTypes.string,
});
-const DIGITS = '0123456789abcdefghijklmnopqrstuvwxyz';
-
/**
* Convert from `value` to `base`.
*/
'use strict';
+import DIGITS from './DIGITS';
+
/**
* Strips the leading prefix from `number` in `base` and returns the remaining
* part of the string.
}
}
+function parse(digit: string, base: number) {
+ if (base > 36 && base <= 62) {
+ const position = DIGITS.indexOf(digit);
+ return position !== -1 && position < base ? position + 1 : NaN;
+ } else {
+ return parseInt(digit, base);
+ }
+}
+
/**
* Breaks the string repsentation of `number` in `base` into an array of decimal
* digits (from least significant to most significant) for easier manipulation.
*/
export default function getDigits(number: string, base: number): Array<number> {
return stripPrefix(number, base).trim().split('').reverse().map(digit => {
- const result = parseInt(digit, base);
+ const result = parse(digit, base);
if (isNaN(result)) {
throw new Error('Invalid digit `' + digit + '` for base `' + base + '`');
}
'use strict';
+import DIGITS from './DIGITS';
+
+function encode(number: string, base: number) {
+ if (base > 36 && base <=62) {
+ return DIGITS[number - 1];
+ } else {
+ return number.toString(base);
+ }
+}
+
/**
* Turns an unpacked arbitrary-precision representation of a number, `digits`,
* (as produced by `getDigits`) back into a string representation in `base`.
return digits
.slice()
.reverse()
- .map(number => number.toString(base))
+ .map(number => encode(number, base))
.join('');
}