Compare commits
No commits in common. "master" and "website" have entirely different histories.
71
Kotlin/.gitignore
vendored
71
Kotlin/.gitignore
vendored
@ -1,8 +1,9 @@
|
||||
# Built application files
|
||||
*.apk
|
||||
*.ap_
|
||||
*.aab
|
||||
|
||||
# Files for the Dalvik VM
|
||||
# Files for the ART/Dalvik VM
|
||||
*.dex
|
||||
|
||||
# Java class files
|
||||
@ -11,6 +12,8 @@
|
||||
# Generated files
|
||||
bin/
|
||||
gen/
|
||||
out/
|
||||
release/
|
||||
|
||||
# Gradle files
|
||||
.gradle/
|
||||
@ -25,16 +28,58 @@ proguard/
|
||||
# Log Files
|
||||
*.log
|
||||
|
||||
.idea/.workspace
|
||||
# Android Studio Navigation editor temp files
|
||||
.navigation/
|
||||
|
||||
# http://stackoverflow.com/questions/16736856/what-should-be-in-my-gitignore-for-an-android-studio-project
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea/workspace.xml
|
||||
/.idea/libraries
|
||||
.DS_Store
|
||||
/build
|
||||
.idea
|
||||
**/*.iml
|
||||
*.hprof
|
||||
**/*.project
|
||||
# Android Studio captures folder
|
||||
captures/
|
||||
|
||||
# IntelliJ
|
||||
*.iml
|
||||
.idea/workspace.xml
|
||||
.idea/tasks.xml
|
||||
.idea/gradle.xml
|
||||
.idea/assetWizardSettings.xml
|
||||
.idea/dictionaries
|
||||
.idea/libraries
|
||||
.idea/caches/build_file_checksums.ser
|
||||
.idea/misc.xml
|
||||
# Android Studio 3 in .gitignore file.
|
||||
.idea/caches
|
||||
.idea/modules.xml
|
||||
# Comment next line if keeping position of elements in Navigation Editor is relevant for you
|
||||
.idea/navEditor.xml
|
||||
.idea/encodings.xml
|
||||
|
||||
# Keystore files
|
||||
# Uncomment the following lines if you do not want to check your keystore files in.
|
||||
#*.jks
|
||||
#*.keystore
|
||||
|
||||
# External native build folder generated in Android Studio 2.2 and later
|
||||
.externalNativeBuild
|
||||
|
||||
# Google Services (e.g. APIs or Firebase)
|
||||
# google-services.json
|
||||
|
||||
# Freeline
|
||||
freeline.py
|
||||
freeline/
|
||||
freeline_project_description.json
|
||||
|
||||
# fastlane
|
||||
fastlane/report.xml
|
||||
fastlane/Preview.html
|
||||
fastlane/screenshots
|
||||
fastlane/test_output
|
||||
fastlane/readme.md
|
||||
|
||||
# Version control
|
||||
vcs.xml
|
||||
|
||||
# lint
|
||||
lint/intermediates/
|
||||
lint/generated/
|
||||
lint/outputs/
|
||||
lint/tmp/
|
||||
# lint/reports/
|
||||
|
||||
BIN
Kotlin/.idea/caches/build_file_checksums.ser
generated
Normal file
BIN
Kotlin/.idea/caches/build_file_checksums.ser
generated
Normal file
Binary file not shown.
19
Kotlin/.idea/gradle.xml
generated
Normal file
19
Kotlin/.idea/gradle.xml
generated
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GradleSettings">
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<GradleProjectSettings>
|
||||
<option name="distributionType" value="DEFAULT_WRAPPED" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="modules">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
<option value="$PROJECT_DIR$/demo" />
|
||||
<option value="$PROJECT_DIR$/lib" />
|
||||
</set>
|
||||
</option>
|
||||
<option name="resolveModulePerSourceSet" value="false" />
|
||||
</GradleProjectSettings>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
44
Kotlin/.idea/misc.xml
generated
Normal file
44
Kotlin/.idea/misc.xml
generated
Normal file
@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="NullableNotNullManager">
|
||||
<option name="myDefaultNullable" value="android.support.annotation.Nullable" />
|
||||
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
|
||||
<option name="myNullables">
|
||||
<value>
|
||||
<list size="10">
|
||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
|
||||
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
|
||||
<item index="2" class="java.lang.String" itemvalue="javax.annotation.CheckForNull" />
|
||||
<item index="3" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
|
||||
<item index="4" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
|
||||
<item index="5" class="java.lang.String" itemvalue="androidx.annotation.Nullable" />
|
||||
<item index="6" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNullable" />
|
||||
<item index="7" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.Nullable" />
|
||||
<item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableDecl" />
|
||||
<item index="9" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableType" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
<option name="myNotNulls">
|
||||
<value>
|
||||
<list size="9">
|
||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
|
||||
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
|
||||
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
|
||||
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
|
||||
<item index="4" class="java.lang.String" itemvalue="androidx.annotation.NonNull" />
|
||||
<item index="5" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNonNull" />
|
||||
<item index="6" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.NonNull" />
|
||||
<item index="7" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullDecl" />
|
||||
<item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullType" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
<option name="id" value="Android" />
|
||||
</component>
|
||||
</project>
|
||||
12
Kotlin/.idea/runConfigurations.xml
generated
Normal file
12
Kotlin/.idea/runConfigurations.xml
generated
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RunConfigurationProducerService">
|
||||
<option name="ignoredProducers">
|
||||
<set>
|
||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
|
||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
|
||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
|
||||
</set>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
@ -1,27 +1,25 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
|
||||
ext.kotlin_version = '1.3.50'
|
||||
|
||||
ext.kotlin_version = '1.3.40'
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.5.0'
|
||||
classpath 'com.android.tools.build:gradle:3.4.1'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
}
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
task clean(type: Delete) {
|
||||
|
||||
1
Kotlin/demo/.gitignore
vendored
Normal file
1
Kotlin/demo/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/build
|
||||
@ -1,29 +1,34 @@
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
apply plugin: 'kotlin-android'
|
||||
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
|
||||
android {
|
||||
|
||||
compileSdkVersion 29
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.wolt.blurhash"
|
||||
minSdkVersion 14
|
||||
targetSdkVersion 29
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
implementation project(path: ':lib')
|
||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.0.2'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||
implementation 'com.google.android.material:material:1.0.0'
|
||||
testImplementation 'junit:junit:4.12'
|
||||
androidTestImplementation 'androidx.test:runner:1.2.0'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
|
||||
}
|
||||
|
||||
@ -0,0 +1,24 @@
|
||||
package com.wolt.blurhashapp
|
||||
|
||||
import androidx.test.InstrumentationRegistry
|
||||
import androidx.test.runner.AndroidJUnit4
|
||||
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
import org.junit.Assert.*
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* See [testing documentation](http://d.android.com/tools/testing).
|
||||
*/
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class ExampleInstrumentedTest {
|
||||
@Test
|
||||
fun useAppContext() {
|
||||
// Context of the app under test.
|
||||
val appContext = InstrumentationRegistry.getTargetContext()
|
||||
assertEquals("com.wolt.blurhash", appContext.packageName)
|
||||
}
|
||||
}
|
||||
@ -1,24 +1,33 @@
|
||||
package com.wolt.blurhashapp
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.widget.EditText
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.wolt.blurhashkt.BlurHashDecoder
|
||||
import com.wolt.blurhashkt.BlurHashDecoder.decode
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
|
||||
private lateinit var etBlurHash: EditText
|
||||
private lateinit var tvDecode: TextView
|
||||
private lateinit var ivBlurHash: ImageView
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_main)
|
||||
val etInput: EditText = findViewById(R.id.etInput)
|
||||
val ivResult: ImageView = findViewById(R.id.ivResult)
|
||||
findViewById<View>(R.id.tvDecode).setOnClickListener {
|
||||
val bitmap = BlurHashDecoder.decode(etInput.text.toString(), 20, 12)
|
||||
ivResult.setImageBitmap(bitmap)
|
||||
}
|
||||
etBlurHash = findViewById(R.id.etBlurHash)
|
||||
tvDecode = findViewById(R.id.tvDecode)
|
||||
ivBlurHash = findViewById(R.id.ivBlurHash)
|
||||
|
||||
tvDecode.setOnClickListener { decodeBlurHash(etBlurHash.text.toString()) }
|
||||
}
|
||||
|
||||
private fun decodeBlurHash(blurHashString: String) {
|
||||
Thread(Runnable {
|
||||
val bitmap = decode(blurHashString, 20, 20, 1f)
|
||||
ivBlurHash.post { ivBlurHash.setImageBitmap(bitmap) }
|
||||
}).start()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="#35000000">
|
||||
|
||||
<item android:id="@android:id/mask">
|
||||
<shape android:shape="rectangle">
|
||||
<corners android:radius="8dp"/>
|
||||
<solid android:color="#ffffff" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
</ripple>
|
||||
@ -1,43 +1,55 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:padding="24dp">
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etInput"
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/tilBlurHash"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:gravity="center_horizontal"
|
||||
android:hint="@string/hint_blurhash"
|
||||
android:inputType="text"
|
||||
android:singleLine="true"
|
||||
android:text="LEHV6nWB2yk8pyo0adR*.7kCMdnj"
|
||||
android:textColor="@color/colorAccent" />
|
||||
android:layout_margin="16dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etBlurHash"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:autofillHints="LEHV6nWB2yk8pyo0adR*.7kCMdnj"
|
||||
android:hint="@string/hint_blurhash"
|
||||
android:inputType="text"
|
||||
android:singleLine="true"/>
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvDecode"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="12dp"
|
||||
android:background="@color/colorPrimary"
|
||||
android:elevation="8dp"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:paddingBottom="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:background="@drawable/bg_blue_rounded_rect_8"
|
||||
android:gravity="center"
|
||||
android:minWidth="100dp"
|
||||
android:minHeight="40dp"
|
||||
android:padding="8dp"
|
||||
android:text="@string/title_button_decode"
|
||||
android:textColor="@color/colorAccent"
|
||||
android:textSize="16sp" />
|
||||
android:textColor="#ffffff"
|
||||
android:textSize="16sp"
|
||||
android:foreground="@drawable/fg_light_rounded_8_rect_btn"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tilBlurHash"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivResult"
|
||||
android:id="@+id/ivBlurHash"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:adjustViewBounds="true" />
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginTop="32dp"
|
||||
android:scaleType="fitXY"
|
||||
app:layout_constraintDimensionRatio="4:3"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tvDecode"/>
|
||||
|
||||
</LinearLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="colorPrimary">#29b6f6</color>
|
||||
<color name="colorPrimaryDark">#0086c3</color>
|
||||
<color name="colorAccent">#444444</color>
|
||||
<color name="colorPrimary">#ff009de0</color>
|
||||
<color name="colorPrimaryDark">#ff009de0</color>
|
||||
<color name="colorAccent">#ff009de0</color>
|
||||
</resources>
|
||||
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
<resources>
|
||||
|
||||
<!-- Base application theme. -->
|
||||
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
|
||||
<!-- Customize your theme here. -->
|
||||
<item name="colorPrimary">@color/colorPrimary</item>
|
||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||
<item name="colorAccent">@color/colorAccent</item>
|
||||
|
||||
@ -0,0 +1,17 @@
|
||||
package com.wolt.blurhashapp
|
||||
|
||||
import org.junit.Test
|
||||
|
||||
import org.junit.Assert.*
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
*
|
||||
* See [testing documentation](http://d.android.com/tools/testing).
|
||||
*/
|
||||
class ExampleUnitTest {
|
||||
@Test
|
||||
fun addition_isCorrect() {
|
||||
assertEquals(4, 2 + 2)
|
||||
}
|
||||
}
|
||||
@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip
|
||||
|
||||
1
Kotlin/lib/.gitignore
vendored
Normal file
1
Kotlin/lib/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/build
|
||||
@ -3,7 +3,6 @@ apply plugin: 'kotlin-android-extensions'
|
||||
apply plugin: 'kotlin-android'
|
||||
|
||||
android {
|
||||
|
||||
compileSdkVersion 29
|
||||
|
||||
defaultConfig {
|
||||
@ -26,5 +25,15 @@ android {
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
|
||||
implementation 'androidx.appcompat:appcompat:1.0.2'
|
||||
implementation "androidx.core:core-ktx:1.0.2"
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
|
||||
testImplementation 'junit:junit:4.12'
|
||||
androidTestImplementation 'androidx.test:runner:1.2.0'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
|
||||
}
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
@ -0,0 +1,26 @@
|
||||
package com.wolt.blurhashkt;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.test.InstrumentationRegistry;
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ExampleInstrumentedTest {
|
||||
@Test
|
||||
public void useAppContext() {
|
||||
// Context of the app under test.
|
||||
Context appContext = InstrumentationRegistry.getTargetContext();
|
||||
|
||||
assertEquals("com.wolt.blurhashkt.test", appContext.getPackageName());
|
||||
}
|
||||
}
|
||||
@ -1 +1,2 @@
|
||||
<manifest package="com.wolt.blurhashkt" />
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.wolt.blurhashkt"/>
|
||||
|
||||
@ -2,121 +2,123 @@ package com.wolt.blurhashkt
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Color
|
||||
import kotlin.math.PI
|
||||
import kotlin.math.cos
|
||||
import kotlin.math.pow
|
||||
import kotlin.math.withSign
|
||||
import java.lang.Math.*
|
||||
|
||||
/**
|
||||
* Created by mike on 31/07/2017.
|
||||
*/
|
||||
object BlurHashDecoder {
|
||||
|
||||
fun decode(blurHash: String?, width: Int, height: Int, punch: Float = 1f): Bitmap? {
|
||||
private val digitCharacters = arrayOf(
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
|
||||
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
|
||||
'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
|
||||
'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
|
||||
'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
|
||||
'y', 'z', '#', '$', '%', '*', '+', ',', '-', '.',
|
||||
':', ';', '=', '?', '@', '[', ']', '^', '_', '{',
|
||||
'|', '}', '~'
|
||||
)
|
||||
|
||||
private val MAX_SIZE = 20
|
||||
|
||||
fun decode(blurHash: String?, width: Int, height: Int, punch: Float): Bitmap? {
|
||||
if (blurHash == null || blurHash.length < 6) {
|
||||
return null
|
||||
}
|
||||
val numCompEnc = decode83(blurHash, 0, 1)
|
||||
val numCompX = (numCompEnc % 9) + 1
|
||||
val numCompY = (numCompEnc / 9) + 1
|
||||
if (blurHash.length != 4 + 2 * numCompX * numCompY) {
|
||||
|
||||
val sizeFlag = blurHash[0].toString().decode83()
|
||||
val numY = (sizeFlag / 9) + 1
|
||||
val numX = (sizeFlag % 9) + 1
|
||||
|
||||
val quantisedMaximumValue = blurHash[1].toString().decode83()
|
||||
val maximumValue = (quantisedMaximumValue + 1) / 166f
|
||||
|
||||
if (blurHash.length != 4 + 2 * numX * numY) {
|
||||
return null
|
||||
}
|
||||
val maxAcEnc = decode83(blurHash, 1, 2)
|
||||
val maxAc = (maxAcEnc + 1) / 166f
|
||||
val colors = Array(numCompX * numCompY) { i ->
|
||||
|
||||
val colors = (0..numX * numY - 1).map { i ->
|
||||
if (i == 0) {
|
||||
val colorEnc = decode83(blurHash, 2, 6)
|
||||
decodeDc(colorEnc)
|
||||
val value = blurHash.substring(2, 6).decode83()
|
||||
decodeDc(value)
|
||||
} else {
|
||||
val from = 4 + i * 2
|
||||
val colorEnc = decode83(blurHash, from, from + 2)
|
||||
decodeAc(colorEnc, maxAc * punch)
|
||||
val startIndex = 4 + i * 2
|
||||
val value = blurHash.substring(startIndex, startIndex + 2).decode83()
|
||||
decodeAc(value, maximumValue * punch)
|
||||
}
|
||||
}
|
||||
return composeBitmap(width, height, numCompX, numCompY, colors)
|
||||
}
|
||||
|
||||
private fun decode83(str: String, from: Int = 0, to: Int = str.length): Int {
|
||||
var result = 0
|
||||
for (i in from until to) {
|
||||
val index = charMap[str[i]] ?: -1
|
||||
if (index != -1) {
|
||||
result = result * 83 + index
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private fun decodeDc(colorEnc: Int): FloatArray {
|
||||
val r = colorEnc shr 16
|
||||
val g = (colorEnc shr 8) and 255
|
||||
val b = colorEnc and 255
|
||||
return floatArrayOf(srgbToLinear(r), srgbToLinear(g), srgbToLinear(b))
|
||||
}
|
||||
|
||||
private fun srgbToLinear(colorEnc: Int): Float {
|
||||
val v = colorEnc / 255f
|
||||
return if (v <= 0.04045f) {
|
||||
(v / 12.92f)
|
||||
} else {
|
||||
((v + 0.055f) / 1.055f).pow(2.4f)
|
||||
}
|
||||
}
|
||||
|
||||
private fun decodeAc(value: Int, maxAc: Float): FloatArray {
|
||||
val r = value / (19 * 19)
|
||||
val g = (value / 19) % 19
|
||||
val b = value % 19
|
||||
return floatArrayOf(
|
||||
signedPow2((r - 9) / 9.0f) * maxAc,
|
||||
signedPow2((g - 9) / 9.0f) * maxAc,
|
||||
signedPow2((b - 9) / 9.0f) * maxAc
|
||||
)
|
||||
}
|
||||
|
||||
private fun signedPow2(value: Float) = value.pow(2f).withSign(value)
|
||||
|
||||
private fun composeBitmap(
|
||||
width: Int, height: Int,
|
||||
numCompX: Int, numCompY: Int,
|
||||
colors: Array<FloatArray>
|
||||
): Bitmap {
|
||||
val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
|
||||
for (y in 0 until height) {
|
||||
for (x in 0 until width) {
|
||||
|
||||
for (y in 0..height - 1) {
|
||||
for (x in 0..width - 1) {
|
||||
var r = 0f
|
||||
var g = 0f
|
||||
var b = 0f
|
||||
for (j in 0 until numCompY) {
|
||||
for (i in 0 until numCompX) {
|
||||
|
||||
for (j in 0..numY - 1) {
|
||||
for (i in 0..numX - 1) {
|
||||
val basis = (cos(PI * x * i / width) * cos(PI * y * j / height)).toFloat()
|
||||
val color = colors[j * numCompX + i]
|
||||
val color = colors[i + j * numX]
|
||||
r += color[0] * basis
|
||||
g += color[1] * basis
|
||||
b += color[2] * basis
|
||||
}
|
||||
}
|
||||
bitmap.setPixel(x, y, Color.rgb(linearToSrgb(r), linearToSrgb(g), linearToSrgb(b)))
|
||||
|
||||
bitmap.setPixel(x, y, Color.rgb(linearToSRgb(r), linearToSRgb(g), linearToSRgb(b)))
|
||||
}
|
||||
}
|
||||
|
||||
return bitmap
|
||||
}
|
||||
|
||||
private fun linearToSrgb(value: Float): Int {
|
||||
val v = value.coerceIn(0f, 1f)
|
||||
return if (v <= 0.0031308f) {
|
||||
(v * 12.92f * 255f + 0.5f).toInt()
|
||||
@Suppress("LoopToCallChain")
|
||||
private fun String.decode83(): Int {
|
||||
var value: Int = 0
|
||||
for (i in 0..this.length - 1) {
|
||||
val digit = digitCharacters.indexOf(this[i])
|
||||
if (digit != -1) {
|
||||
value = value * 83 + digit
|
||||
}
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
private fun decodeDc(value: Int): Array<Float> {
|
||||
val intR = value shr 16
|
||||
val intG = (value shr 8) and 255
|
||||
val intB = value and 255
|
||||
return arrayOf(sRgbToLinear(intR), sRgbToLinear(intG), sRgbToLinear(intB))
|
||||
}
|
||||
|
||||
fun sRgbToLinear(value: Int): Float {
|
||||
val v = value / 255f
|
||||
return if (v <= 0.04045) (v / 12.92f) else (pow((v + 0.055) / 1.055, 2.4).toFloat())
|
||||
}
|
||||
|
||||
private fun decodeAc(value: Int, maximumValue: Float): Array<Float> {
|
||||
val quantR = value / (19 * 19)
|
||||
val quantG = (value / 19) % 19
|
||||
val quantB = value % 19
|
||||
return arrayOf(
|
||||
signPow((quantR - 9) / 9.0, 2.0) * maximumValue,
|
||||
signPow((quantG - 9) / 9.0, 2.0) * maximumValue,
|
||||
signPow((quantB - 9) / 9.0, 2.0) * maximumValue
|
||||
)
|
||||
}
|
||||
|
||||
private fun signPow(value: Double, exp: Double) = copySign(pow(abs(value), exp), value).toFloat()
|
||||
|
||||
private fun linearToSRgb(value: Float): Int {
|
||||
val v = max(0f, min(1f, value))
|
||||
if (v <= 0.0031308f) {
|
||||
return (v * 12.92f * 255 + 0.5f).toInt()
|
||||
} else {
|
||||
((1.055f * v.pow(1 / 2.4f) - 0.055f) * 255 + 0.5f).toInt()
|
||||
return ((1.055f * pow(v.toDouble(), 1 / 2.4) - 0.055f) * 255 + 0.5f).toInt()
|
||||
}
|
||||
}
|
||||
|
||||
private val charMap = listOf(
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
|
||||
'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
|
||||
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
|
||||
'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '#', '$', '%', '*', '+', ',',
|
||||
'-', '.', ':', ';', '=', '?', '@', '[', ']', '^', '_', '{', '|', '}', '~'
|
||||
)
|
||||
.mapIndexed { i, c -> c to i }
|
||||
.toMap()
|
||||
|
||||
}
|
||||
|
||||
3
Kotlin/lib/src/main/res/values/strings.xml
Normal file
3
Kotlin/lib/src/main/res/values/strings.xml
Normal file
@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<string name="app_name">BlurHashKt</string>
|
||||
</resources>
|
||||
@ -0,0 +1,17 @@
|
||||
package com.wolt.blurhashkt;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
public class ExampleUnitTest {
|
||||
@Test
|
||||
public void addition_isCorrect() {
|
||||
assertEquals(4, 2 + 2);
|
||||
}
|
||||
}
|
||||
34
Readme.md
34
Readme.md
@ -40,19 +40,18 @@ So far, we have created these implementations:
|
||||
There is also an example app to play around with the algorithm.
|
||||
* [Kotlin](Kotlin) - A decoder implementation for Android.
|
||||
* [TypeScript](TypeScript) - Encoder and decoder implementations, and an example page to test.
|
||||
* [Python](https://github.com/woltapp/blurhash-python) - Integration of the C encoder code into Python.
|
||||
|
||||
These cover our use cases, but could probably use polishing, extending and improving. There are also these third party implementations that we know of:
|
||||
|
||||
* [Python](https://github.com/creditornot/blurhash-python) - Integration of the C encoder code into Python.
|
||||
* [Pure Python](https://github.com/halcy/blurhash-python) - Implementation of both the encoder and decoder in pure Python.
|
||||
* [One version in Go](https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&uact=8&ved=2ahUKEwjJ9ueT9pXjAhXRw6YKHfrGBNcQFjAAegQIABAB&url=https%3A%2F%2Fgithub.com%2Fbbrks%2Fgo-blurhash&usg=AOvVaw2alZSHvT7HbublYbpNn9fY), and [another version in Go](https://github.com/buckket/go-blurhash).
|
||||
* [PHP](https://github.com/kornrunner/php-blurhash) - Encoder and decoder implementations in pure PHP.
|
||||
* [Java](https://github.com/hsch/blurhash-java) - Encoder implementation in Java.
|
||||
* [Clojure](https://github.com/siili-core/blurhash) - Encoder and decoder implementations in Clojure.
|
||||
* [Nim](https://github.com/SolitudeSF/blurhash) - Encoder and decoder implementation in pure Nim.
|
||||
* [Rust and WebAssembly](https://github.com/fpapado/blurhash-rust-wasm) - Encoder and decoder implementations in Rust. Distributed as both native Rust and WebAssembly packages.
|
||||
|
||||
Perhaps you'd like to help extend this list? Which brings us to...
|
||||
These cover our use cases, but could probably use polishing, extending and improving. Perhaps you'd like to help?
|
||||
Which brings us to...
|
||||
|
||||
## Users
|
||||
|
||||
Who uses BlurHash? Here are some projects we know about:
|
||||
|
||||
* [Wolt](http://wolt.com/) - We are of course using it ourselves. BlurHashes are used in the mobile clients on iOS and Android, as well as on the web, as placeholders during image loading.
|
||||
* [Mastodon](https://github.com/tootsuite/mastodon) - The Mastodon decentralised social media network uses BlurHashes both as loading placeholders, as well as for hiding media marked as sensitive.
|
||||
|
||||
## Contributing
|
||||
|
||||
@ -67,13 +66,6 @@ You can file a pull request with us, or you can start your own repo and project
|
||||
|
||||
If you do want to contribute to this project, we have a [code of conduct](CodeOfConduct.md).
|
||||
|
||||
## Users
|
||||
|
||||
Who uses BlurHash? Here are some projects we know about:
|
||||
|
||||
* [Wolt](http://wolt.com/) - We are of course using it ourselves. BlurHashes are used in the mobile clients on iOS and Android, as well as on the web, as placeholders during image loading.
|
||||
* [Mastodon](https://github.com/tootsuite/mastodon) - The Mastodon decentralised social media network uses BlurHashes both as loading placeholders, as well as for hiding media marked as sensitive.
|
||||
|
||||
## Good Questions
|
||||
|
||||
### How fast is encoding? Decoding?
|
||||
@ -130,7 +122,7 @@ option. It might also be awkward to copy-paste, depending on OS capabilities.
|
||||
|
||||
If you think it can be done and is worth it, though, do make your own version and show us! We'd love to see it in action.
|
||||
|
||||
### What about other basis representations than DCT?
|
||||
### What about other basis represenations than DCT?
|
||||
|
||||
This is something we'd *love* to try. The DCT looks quite ugly when you increase the number of components, probably because
|
||||
the shape of the basis functions becomes too visible. Using a different basis with more aesthetically pleasing shape might be
|
||||
@ -148,10 +140,6 @@ to see what you can come up with!
|
||||
* [Olli Mahlamäki](https://github.com/omahlama) - TypeScript decoder and encoder implementations
|
||||
* [Atte Lautanala](https://github.com/lautat) - Python integration
|
||||
* [Lorenz Diener](https://github.com/halcy) - Pure Python implementation
|
||||
* [Boris Momčilović](https://github.com/kornrunner) - Pure PHP implementation
|
||||
* [Hendrik Schnepel](https://github.com/hsch) - Java encoder implementation
|
||||
* [Tuomo Virolainen](https://github.com/tvirolai) - Clojure implementation
|
||||
* [Fotis Papadogeorgopoulos](https://github.com/fpapado) - Rust and WebAssembly implementation
|
||||
* _Your name here?_
|
||||
|
||||
## License
|
||||
|
||||
@ -32,8 +32,6 @@
|
||||
1B6C72042272453D000D3BB1 /* ColourSpace.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1BAA607C1FF422AE00E42DD7 /* ColourSpace.swift */; };
|
||||
1B6C72052272453D000D3BB1 /* StringCoding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1BAA607A1FF40D8900E42DD7 /* StringCoding.swift */; };
|
||||
1B6C72062272453D000D3BB1 /* ColourProbes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1BDE56D02011EC5F00569DCB /* ColourProbes.swift */; };
|
||||
1B83DED122D88D1500CAA12F /* EscapeSequences.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B83DED022D88D1500CAA12F /* EscapeSequences.swift */; };
|
||||
1B83DED222D88D1500CAA12F /* EscapeSequences.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B83DED022D88D1500CAA12F /* EscapeSequences.swift */; };
|
||||
1BAA606D1FF40A0800E42DD7 /* BlurHashEncode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B49CD261EC47243006F8E7D /* BlurHashEncode.swift */; };
|
||||
1BAA606E1FF40A0B00E42DD7 /* BlurHashDecode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B49CD281EC4724C006F8E7D /* BlurHashDecode.swift */; };
|
||||
1BAA60711FF40A2F00E42DD7 /* BlurHash.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1BAA60701FF40A2F00E42DD7 /* BlurHash.swift */; };
|
||||
@ -133,7 +131,6 @@
|
||||
1B49CD281EC4724C006F8E7D /* BlurHashDecode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BlurHashDecode.swift; sourceTree = "<group>"; };
|
||||
1B6C71F122724500000D3BB1 /* BlurHashKit copy-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "BlurHashKit copy-Info.plist"; path = "/Users/dag/Code/Toot/BlurHash/BlurHashKit copy-Info.plist"; sourceTree = "<absolute>"; };
|
||||
1B6C71F62272451E000D3BB1 /* libBlurHashKit.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libBlurHashKit.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
1B83DED022D88D1500CAA12F /* EscapeSequences.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EscapeSequences.swift; sourceTree = "<group>"; };
|
||||
1BAA60701FF40A2F00E42DD7 /* BlurHash.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlurHash.swift; sourceTree = "<group>"; };
|
||||
1BAA60721FF40AEA00E42DD7 /* ToString.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToString.swift; sourceTree = "<group>"; };
|
||||
1BAA60741FF40AF200E42DD7 /* FromString.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FromString.swift; sourceTree = "<group>"; };
|
||||
@ -341,7 +338,6 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
1BAA60701FF40A2F00E42DD7 /* BlurHash.swift */,
|
||||
1B83DED022D88D1500CAA12F /* EscapeSequences.swift */,
|
||||
1BAA60741FF40AF200E42DD7 /* FromString.swift */,
|
||||
1BAA60721FF40AEA00E42DD7 /* ToString.swift */,
|
||||
1BAA60781FF40C5800E42DD7 /* FromUIImage.swift */,
|
||||
@ -600,7 +596,6 @@
|
||||
1BAA60751FF40AF200E42DD7 /* FromString.swift in Sources */,
|
||||
1BAA607B1FF40D8900E42DD7 /* StringCoding.swift in Sources */,
|
||||
1BAA60771FF40C4C00E42DD7 /* ToUIImage.swift in Sources */,
|
||||
1B83DED122D88D1500CAA12F /* EscapeSequences.swift in Sources */,
|
||||
1BAA60731FF40AEA00E42DD7 /* ToString.swift in Sources */,
|
||||
1BC34D8020098E2F00A17481 /* Generation.swift in Sources */,
|
||||
1BDE56D12011EC5F00569DCB /* ColourProbes.swift in Sources */,
|
||||
@ -618,7 +613,6 @@
|
||||
1B6C72002272453D000D3BB1 /* FromUIImage.swift in Sources */,
|
||||
1B6C72042272453D000D3BB1 /* ColourSpace.swift in Sources */,
|
||||
1B6C72052272453D000D3BB1 /* StringCoding.swift in Sources */,
|
||||
1B83DED222D88D1500CAA12F /* EscapeSequences.swift in Sources */,
|
||||
1B6C71FF2272453D000D3BB1 /* ToString.swift in Sources */,
|
||||
1B6C71FD2272453D000D3BB1 /* BlurHash.swift in Sources */,
|
||||
1B6C72062272453D000D3BB1 /* ColourProbes.swift in Sources */,
|
||||
|
||||
@ -1,21 +1,21 @@
|
||||
import Foundation
|
||||
|
||||
extension BlurHash {
|
||||
public func linearRgb(atX: Float) -> (Float, Float, Float) {
|
||||
public func linearRGB(atX: Float) -> (Float, Float, Float) {
|
||||
return components[0].enumerated().reduce((0, 0, 0)) { (sum, xEnumerated) in
|
||||
let (x, component) = xEnumerated
|
||||
return sum + component * cos(Float.pi * Float(x) * atX)
|
||||
}
|
||||
}
|
||||
|
||||
public func linearRgb(atY: Float) -> (Float, Float, Float) {
|
||||
public func linearRGB(atY: Float) -> (Float, Float, Float) {
|
||||
return components.enumerated().reduce((0, 0, 0)) { (sum, yEnumerated) in
|
||||
let (y, xComponents) = yEnumerated
|
||||
return sum + xComponents[0] * cos(Float.pi * Float(y) * atY)
|
||||
}
|
||||
}
|
||||
|
||||
public func linearRgb(at position: (Float, Float)) -> (Float, Float, Float) {
|
||||
public func linearRGB(at position: (Float, Float)) -> (Float, Float, Float) {
|
||||
return components.enumerated().reduce((0, 0, 0)) { (sum, yEnumerated) in
|
||||
let (y, xComponents) = yEnumerated
|
||||
return xComponents.enumerated().reduce(sum) { (sum, xEnumerated) in
|
||||
@ -25,48 +25,30 @@ extension BlurHash {
|
||||
}
|
||||
}
|
||||
|
||||
public func linearRgb(from upperLeft: (Float, Float), to lowerRight: (Float, Float)) -> (Float, Float, Float) {
|
||||
return components.enumerated().reduce((0, 0, 0)) { (sum, yEnumerated) in
|
||||
let (y, xComponents) = yEnumerated
|
||||
return xComponents.enumerated().reduce(sum) { (sum, xEnumerated) in
|
||||
let (x, component) = xEnumerated
|
||||
let horizontalAverage: Float = x == 0 ? 1 : (sin(Float.pi * Float(x) * lowerRight.0) - sin(Float.pi * Float(x) * upperLeft.0)) / (Float(x) * Float.pi * (lowerRight.0 - upperLeft.0))
|
||||
let veritcalAverage: Float = y == 0 ? 1 : (sin(Float.pi * Float(y) * lowerRight.1) - sin(Float.pi * Float(y) * upperLeft.1)) / (Float(y) * Float.pi * (lowerRight.1 - upperLeft.1))
|
||||
return sum + component * horizontalAverage * veritcalAverage
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func linearRgb(at upperLeft: (Float, Float), size: (Float, Float)) -> (Float, Float, Float) {
|
||||
return linearRgb(from: upperLeft, to: (upperLeft.0 + size.0, upperLeft.1 + size.1))
|
||||
}
|
||||
|
||||
public var averageLinearRgb: (Float, Float, Float) {
|
||||
public var averageLinearRGB: (Float, Float, Float) {
|
||||
return components[0][0]
|
||||
}
|
||||
|
||||
public var leftEdgeLinearRgb: (Float, Float, Float) { return linearRgb(atX: 0) }
|
||||
public var rightEdgeLinearRgb: (Float, Float, Float) { return linearRgb(atX: 1) }
|
||||
public var topEdgeLinearRgb: (Float, Float, Float) { return linearRgb(atY: 0) }
|
||||
public var bottomEdgeLinearRgb: (Float, Float, Float) { return linearRgb(atY: 1) }
|
||||
public var topLeftCornerLinearRgb: (Float, Float, Float) { return linearRgb(at: (0, 0)) }
|
||||
public var topRightCornerLinearRgb: (Float, Float, Float) { return linearRgb(at: (1, 0)) }
|
||||
public var bottomLeftCornerLinearRgb: (Float, Float, Float) { return linearRgb(at: (0, 1)) }
|
||||
public var bottomRightCornerLinearRgb: (Float, Float, Float) { return linearRgb(at: (1, 1)) }
|
||||
public var leftEdgeLinearRGB: (Float, Float, Float) { return linearRGB(atX: 0) }
|
||||
public var rightEdgeLinearRGB: (Float, Float, Float) { return linearRGB(atX: 1) }
|
||||
public var topEdgeLinearRGB: (Float, Float, Float) { return linearRGB(atY: 0) }
|
||||
public var bottomEdgeLinearRGB: (Float, Float, Float) { return linearRGB(atY: 1) }
|
||||
public var topLeftCornerLinearRGB: (Float, Float, Float) { return linearRGB(at: (0, 0)) }
|
||||
public var topRightCornerLinearRGB: (Float, Float, Float) { return linearRGB(at: (1, 0)) }
|
||||
public var bottomLeftCornerLinearRGB: (Float, Float, Float) { return linearRGB(at: (0, 1)) }
|
||||
public var bottomRightCornerLinearRGB: (Float, Float, Float) { return linearRGB(at: (1, 1)) }
|
||||
}
|
||||
|
||||
extension BlurHash {
|
||||
public func isDark(linearRgb rgb: (Float, Float, Float)) -> Bool {
|
||||
public func isDark(linearRGB rgb: (Float, Float, Float)) -> Bool {
|
||||
return rgb.0 * 0.299 + rgb.1 * 0.587 + rgb.2 * 0.114 < 0.5
|
||||
}
|
||||
|
||||
public var isDark: Bool { return isDark(linearRgb: averageLinearRgb) }
|
||||
public var isDark: Bool { return isDark(linearRGB: averageLinearRGB) }
|
||||
|
||||
public func isDark(atX x: Float) -> Bool { return isDark(linearRgb: linearRgb(atX: x)) }
|
||||
public func isDark(atY y: Float) -> Bool { return isDark(linearRgb: linearRgb(atY: y)) }
|
||||
public func isDark(at position: (Float, Float)) -> Bool { return isDark(linearRgb: linearRgb(at: position)) }
|
||||
public func isDark(from upperLeft: (Float, Float), to lowerRight: (Float, Float)) -> Bool { return isDark(linearRgb: linearRgb(from: upperLeft, to: lowerRight)) }
|
||||
public func isDark(at upperLeft: (Float, Float), size: (Float, Float)) -> Bool { return isDark(linearRgb: linearRgb(at: upperLeft, size: size)) }
|
||||
public func isDark(atX x: Float) -> Bool { return isDark(linearRGB: linearRGB(atX: x)) }
|
||||
public func isDark(atY y: Float) -> Bool { return isDark(linearRGB: linearRGB(atY: y)) }
|
||||
public func isDark(at position: (Float, Float)) -> Bool { return isDark(linearRGB: linearRGB(at: position)) }
|
||||
|
||||
public var isLeftEdgeDark: Bool { return isDark(atX: 0) }
|
||||
public var isRightEdgeDark: Bool { return isDark(atX: 1) }
|
||||
|
||||
@ -1,36 +0,0 @@
|
||||
import Foundation
|
||||
|
||||
extension BlurHash {
|
||||
var twoByThreeEscapeSequence: String {
|
||||
let areas: [(from: (Float, Float), to: (Float, Float))] = [
|
||||
(from: (0, 0), to: (0.333, 0.5)),
|
||||
(from: (0, 0.5), to: (0.333, 1.0)),
|
||||
(from: (0.333, 0), to: (0.666, 0.5)),
|
||||
(from: (0.333, 0.5), to: (0.666, 1.0)),
|
||||
(from: (0.666, 0), to: (1.0, 0.5)),
|
||||
(from: (0.666, 0.5), to: (1.0, 1.0)),
|
||||
]
|
||||
|
||||
let rgb: [(Float, Float, Float)] = areas.map { area in
|
||||
linearRgb(from: area.from, to: area.to)
|
||||
}
|
||||
|
||||
let maxRgb: (Float, Float, Float) = rgb.reduce((-Float.infinity, -Float.infinity, -Float.infinity), max)
|
||||
let minRgb: (Float, Float, Float) = rgb.reduce((Float.infinity, Float.infinity, Float.infinity), min)
|
||||
|
||||
let positiveScale: (Float, Float, Float) = ((1, 1, 1) - averageLinearRgb) / (maxRgb - averageLinearRgb)
|
||||
let negativeScale: (Float, Float, Float) = averageLinearRgb / (averageLinearRgb - minRgb)
|
||||
let scale: (Float, Float, Float) = min(positiveScale, negativeScale)
|
||||
|
||||
let scaledRgb: [(Float, Float, Float)] = rgb.map { rgb in
|
||||
return (rgb - averageLinearRgb) * scale + averageLinearRgb
|
||||
}
|
||||
|
||||
let c = scaledRgb.map { rgb in
|
||||
return (linearTosRGB(rgb.0) / 51) * 36 + (linearTosRGB(rgb.1) / 51) * 6 + (linearTosRGB(rgb.2) / 51) + 16
|
||||
}
|
||||
|
||||
return "\u{1b}[38;5;\(c[1]);48;5;\(c[0])m▄\u{1b}[38;5;\(c[3]);48;5;\(c[2])m▄\u{1b}[38;5;\(c[5]);48;5;\(c[4])m▄\u{1b}[m"
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,10 +8,6 @@ func -(lhs: (Float, Float, Float), rhs: (Float, Float, Float)) -> (Float, Float,
|
||||
return (lhs.0 - rhs.0, lhs.1 - rhs.1, lhs.2 - rhs.2)
|
||||
}
|
||||
|
||||
func *(lhs: (Float, Float, Float), rhs: (Float, Float, Float)) -> (Float, Float, Float) {
|
||||
return (lhs.0 * rhs.0, lhs.1 * rhs.1, lhs.2 * rhs.2)
|
||||
}
|
||||
|
||||
func *(lhs: (Float, Float, Float), rhs: Float) -> (Float, Float, Float) {
|
||||
return (lhs.0 * rhs, lhs.1 * rhs, lhs.2 * rhs)
|
||||
}
|
||||
@ -20,10 +16,6 @@ func *(lhs: Float, rhs: (Float, Float, Float)) -> (Float, Float, Float) {
|
||||
return (lhs * rhs.0, lhs * rhs.1, lhs * rhs.2)
|
||||
}
|
||||
|
||||
func /(lhs: (Float, Float, Float), rhs: (Float, Float, Float)) -> (Float, Float, Float) {
|
||||
return (lhs.0 / rhs.0, lhs.1 / rhs.1, lhs.2 / rhs.2)
|
||||
}
|
||||
|
||||
func /(lhs: (Float, Float, Float), rhs: Float) -> (Float, Float, Float) {
|
||||
return (lhs.0 / rhs, lhs.1 / rhs, lhs.2 / rhs)
|
||||
}
|
||||
@ -43,11 +35,3 @@ func *=(lhs: inout (Float, Float, Float), rhs: Float) {
|
||||
func /=(lhs: inout (Float, Float, Float), rhs: Float) {
|
||||
lhs = lhs / rhs
|
||||
}
|
||||
|
||||
func min(_ a: (Float, Float, Float), _ b: (Float, Float, Float)) -> (Float, Float, Float) {
|
||||
return (min(a.0, b.0), min(a.1, b.1), min(a.2, b.2))
|
||||
}
|
||||
|
||||
func max(_ a: (Float, Float, Float), _ b: (Float, Float, Float)) -> (Float, Float, Float) {
|
||||
return (max(a.0, b.0), max(a.1, b.1), max(a.2, b.2))
|
||||
}
|
||||
|
||||
@ -1,78 +1,7 @@
|
||||
# blurhash
|
||||
|
||||
[](https://npmjs.org/package/blurhash)
|
||||
[](https://npmjs.org/package/blurhash)
|
||||
|
||||
> JavaScript encoder and decoder for the [Wolt BlurHash](https://github.com/woltapp/blurhash) algorithm
|
||||
# BlurHash (TypeScript)
|
||||
|
||||
## Install
|
||||
|
||||
```sh
|
||||
npm install --save blurhash
|
||||
```
|
||||
|
||||
See [react-blurhash](https://github.com/woltapp/react-blurhash) to use blurhash with React.
|
||||
|
||||
## API
|
||||
|
||||
### `decode(blurhash: string, width: number, height: number, punch?: number) => Uint8ClampedArray`
|
||||
|
||||
> Decodes a blurhash string to pixels
|
||||
|
||||
#### Example
|
||||
|
||||
```js
|
||||
import { decode } from "blurhash";
|
||||
|
||||
const pixels = decode("LEHV6nWB2yk8pyo0adR*.7kCMdnj", 32, 32);
|
||||
|
||||
const canvas = document.createElement("canvas");
|
||||
const ctx = canvas.getContext("2d");
|
||||
const imageData = ctx.createImageData(width, height);
|
||||
imageData.data.set(pixels);
|
||||
ctx.putImageData(imageData, 0, 0);
|
||||
document.body.append(canvas);
|
||||
```
|
||||
|
||||
### `encode(pixels: Uint8ClampedArray, width: number, height: number, componentX: number, componentY: number) => string`
|
||||
|
||||
> Encodes pixels to a blurhash string
|
||||
|
||||
```js
|
||||
import { encode } from "blurhash";
|
||||
|
||||
const loadImage = async src =>
|
||||
new Promise((resolve, reject) => {
|
||||
const img = new Image();
|
||||
img.onload = () => resolve(img);
|
||||
img.onerror = (...args) => reject(args);
|
||||
img.src = src;
|
||||
});
|
||||
|
||||
const getImageData = image => {
|
||||
const canvas = document.createElement("canvas");
|
||||
canvas.width = image.width;
|
||||
canvas.height = image.height;
|
||||
const context = canvas.getContext("2d");
|
||||
context.drawImage(image, 0, 0);
|
||||
return context.getImageData(0, 0, image.width, image.height);
|
||||
};
|
||||
|
||||
const encodeImageToBlurhash = async imageUrl => {
|
||||
const image = await loadImage(imageUrl);
|
||||
const imageData = getImageData(image);
|
||||
return encode(imageData.data, imageData.width, imageData.height, 4, 4);
|
||||
};
|
||||
```
|
||||
|
||||
### `isBlurhashValid(blurhash: string) => { result: boolean; errorReason?: string }`
|
||||
|
||||
```js
|
||||
import { isBlurhashValid } from "blurhash";
|
||||
|
||||
const validRes = isBlurhashValid("LEHV6nWB2yk8pyo0adR*.7kCMdnj");
|
||||
// { result: true }
|
||||
|
||||
const invalidRes = isBlurhashValid("???");
|
||||
// { result: false, errorReason: "The blurhash string must be at least 6 characters" }
|
||||
```
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "blurhash",
|
||||
"version": "1.1.3",
|
||||
"version": "1.1.2",
|
||||
"description": "Encoder and decoder for the Wolt BlurHash algorithm.",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
@ -29,9 +29,9 @@
|
||||
"devDependencies": {
|
||||
"prettier": "1.18.2",
|
||||
"ts-loader": "6.0.4",
|
||||
"typescript": "3.5.3",
|
||||
"webpack": "4.38.0",
|
||||
"webpack-cli": "^3.3.6",
|
||||
"typescript": "3.5.2",
|
||||
"webpack": "4.35.0",
|
||||
"webpack-cli": "^3.3.5",
|
||||
"webpack-dev-server": "3.7.2"
|
||||
}
|
||||
}
|
||||
|
||||
@ -22,9 +22,9 @@
|
||||
integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==
|
||||
|
||||
"@types/node@*":
|
||||
version "12.6.8"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.6.8.tgz#e469b4bf9d1c9832aee4907ba8a051494357c12c"
|
||||
integrity sha512-aX+gFgA5GHcDi89KG5keey2zf0WfZk/HAQotEamsK2kbey+8yGKcson0hbK8E+v0NArlCJQCqMP161YhV6ZXLg==
|
||||
version "12.0.10"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.0.10.tgz#51babf9c7deadd5343620055fc8aff7995c8b031"
|
||||
integrity sha512-LcsGbPomWsad6wmMNv7nBLw7YYYyfdYcz6xryKYQhx89c3XXan+8Q6AJ43G5XDIaklaVkK3mE4fCb0SBvMiPSQ==
|
||||
|
||||
"@webassemblyjs/ast@1.8.5":
|
||||
version "1.8.5"
|
||||
@ -195,10 +195,15 @@ accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7:
|
||||
mime-types "~2.1.24"
|
||||
negotiator "0.6.2"
|
||||
|
||||
acorn@^6.2.0:
|
||||
version "6.2.1"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.2.1.tgz#3ed8422d6dec09e6121cc7a843ca86a330a86b51"
|
||||
integrity sha512-JD0xT5FCRDNyjDda3Lrg/IxFscp9q4tiYtxE1/nOzlKCk7hIRuYjhq1kCNkbPjMRMZuFq20HNQn1I9k8Oj0E+Q==
|
||||
acorn-dynamic-import@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz#482210140582a36b83c3e342e1cfebcaa9240948"
|
||||
integrity sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw==
|
||||
|
||||
acorn@^6.0.5:
|
||||
version "6.1.1"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.1.1.tgz#7d25ae05bb8ad1f9b699108e1094ecd7884adc1f"
|
||||
integrity sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==
|
||||
|
||||
ajv-errors@^1.0.0:
|
||||
version "1.0.1"
|
||||
@ -206,14 +211,14 @@ ajv-errors@^1.0.0:
|
||||
integrity sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==
|
||||
|
||||
ajv-keywords@^3.1.0:
|
||||
version "3.4.1"
|
||||
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.4.1.tgz#ef916e271c64ac12171fd8384eaae6b2345854da"
|
||||
integrity sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==
|
||||
version "3.4.0"
|
||||
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.4.0.tgz#4b831e7b531415a7cc518cd404e73f6193c6349d"
|
||||
integrity sha512-aUjdRFISbuFOl0EIZc+9e4FfZp0bDZgAdOOf30bJmw8VM9v84SHyVyxDfbWxpGYbdZD/9XoKxfHVNmxPkhwyGw==
|
||||
|
||||
ajv@^6.1.0:
|
||||
version "6.10.2"
|
||||
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.2.tgz#d3cea04d6b017b2894ad69040fec8b623eb4bd52"
|
||||
integrity sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==
|
||||
version "6.10.0"
|
||||
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.0.tgz#90d0d54439da587cd7e843bfb7045f50bd22bdf1"
|
||||
integrity sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==
|
||||
dependencies:
|
||||
fast-deep-equal "^2.0.1"
|
||||
fast-json-stable-stringify "^2.0.0"
|
||||
@ -562,17 +567,16 @@ bytes@3.1.0:
|
||||
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6"
|
||||
integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==
|
||||
|
||||
cacache@^12.0.2:
|
||||
version "12.0.2"
|
||||
resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.2.tgz#8db03205e36089a3df6954c66ce92541441ac46c"
|
||||
integrity sha512-ifKgxH2CKhJEg6tNdAwziu6Q33EvuG26tYcda6PT3WKisZcYDXsnEdnRv67Po3yCzFfaSoMjGZzJyD2c3DT1dg==
|
||||
cacache@^11.3.2:
|
||||
version "11.3.3"
|
||||
resolved "https://registry.yarnpkg.com/cacache/-/cacache-11.3.3.tgz#8bd29df8c6a718a6ebd2d010da4d7972ae3bbadc"
|
||||
integrity sha512-p8WcneCytvzPxhDvYp31PD039vi77I12W+/KfR9S8AZbaiARFBCpsPJS+9uhWfeBfeAtW7o/4vt3MUqLkbY6nA==
|
||||
dependencies:
|
||||
bluebird "^3.5.5"
|
||||
chownr "^1.1.1"
|
||||
figgy-pudding "^3.5.1"
|
||||
glob "^7.1.4"
|
||||
graceful-fs "^4.1.15"
|
||||
infer-owner "^1.0.3"
|
||||
lru-cache "^5.1.1"
|
||||
mississippi "^3.0.0"
|
||||
mkdirp "^0.5.1"
|
||||
@ -632,9 +636,9 @@ chokidar@^2.0.2, chokidar@^2.1.6:
|
||||
fsevents "^1.2.7"
|
||||
|
||||
chownr@^1.1.1:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.2.tgz#a18f1e0b269c8a6a5d3c86eb298beb14c3dd7bf6"
|
||||
integrity sha512-GkfeAQh+QNy3wquu9oIZr6SS5x7wGdSgNQvD10X3r+AZr1Oys22HW8kAmDMvNg2+Dm0TeGaEuO8gFwdBXxwO8A==
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.1.tgz#54726b8b8fff4df053c42187e801fb4412df1494"
|
||||
integrity sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==
|
||||
|
||||
chrome-trace-event@^1.0.0:
|
||||
version "1.0.2"
|
||||
@ -704,7 +708,7 @@ color-name@1.1.3:
|
||||
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
|
||||
integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
|
||||
|
||||
commander@^2.20.0:
|
||||
commander@^2.19.0:
|
||||
version "2.20.0"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422"
|
||||
integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==
|
||||
@ -1061,9 +1065,9 @@ ee-first@1.1.1:
|
||||
integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
|
||||
|
||||
elliptic@^6.0.0:
|
||||
version "6.5.0"
|
||||
resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.0.tgz#2b8ed4c891b7de3200e14412a5b8248c7af505ca"
|
||||
integrity sha512-eFOJTMyCYb7xtE/caJ6JJu+bhi67WCYNbkGSknu20pmM8Ke/bqOfdnZWxyoGN26JgfxTbXrsCkEw4KheCT/KGg==
|
||||
version "6.4.1"
|
||||
resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.1.tgz#c2d0b7776911b86722c632c3c06c60f2f819939a"
|
||||
integrity sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==
|
||||
dependencies:
|
||||
bn.js "^4.4.0"
|
||||
brorand "^1.0.1"
|
||||
@ -1328,7 +1332,7 @@ finalhandler@~1.1.2:
|
||||
statuses "~1.5.0"
|
||||
unpipe "~1.0.0"
|
||||
|
||||
find-cache-dir@^2.1.0:
|
||||
find-cache-dir@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7"
|
||||
integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==
|
||||
@ -1533,9 +1537,9 @@ globby@^6.1.0:
|
||||
pinkie-promise "^2.0.0"
|
||||
|
||||
graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.0.tgz#8d8fdc73977cb04104721cb53666c1ca64cd328b"
|
||||
integrity sha512-jpSvDPV4Cq/bgtpndIWbI5hmYxhQGHPC4d4cqBPb4DLniCfhJokdXhwhaDuLBGLQdvvRum/UiX6ECVIPvDXqdg==
|
||||
version "4.1.15"
|
||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00"
|
||||
integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==
|
||||
|
||||
handle-thing@^2.0.0:
|
||||
version "2.0.0"
|
||||
@ -1635,7 +1639,7 @@ http-deceiver@^1.2.7:
|
||||
resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87"
|
||||
integrity sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=
|
||||
|
||||
http-errors@1.7.2:
|
||||
http-errors@1.7.2, http-errors@~1.7.2:
|
||||
version "1.7.2"
|
||||
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f"
|
||||
integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==
|
||||
@ -1656,17 +1660,6 @@ http-errors@~1.6.2:
|
||||
setprototypeof "1.1.0"
|
||||
statuses ">= 1.4.0 < 2"
|
||||
|
||||
http-errors@~1.7.2:
|
||||
version "1.7.3"
|
||||
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06"
|
||||
integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==
|
||||
dependencies:
|
||||
depd "~1.1.2"
|
||||
inherits "2.0.4"
|
||||
setprototypeof "1.1.1"
|
||||
statuses ">= 1.5.0 < 2"
|
||||
toidentifier "1.0.0"
|
||||
|
||||
"http-parser-js@>=0.4.0 <0.4.11":
|
||||
version "0.4.10"
|
||||
resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.4.10.tgz#92c9c1374c35085f75db359ec56cc257cbb93fa4"
|
||||
@ -1733,11 +1726,6 @@ imurmurhash@^0.1.4:
|
||||
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
|
||||
integrity sha1-khi5srkoojixPcT7a21XbyMUU+o=
|
||||
|
||||
infer-owner@^1.0.3:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467"
|
||||
integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==
|
||||
|
||||
inflight@^1.0.4:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
|
||||
@ -1746,7 +1734,7 @@ inflight@^1.0.4:
|
||||
once "^1.3.0"
|
||||
wrappy "1"
|
||||
|
||||
inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3:
|
||||
inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||
@ -1794,16 +1782,11 @@ ip@^1.1.0, ip@^1.1.5:
|
||||
resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a"
|
||||
integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=
|
||||
|
||||
ipaddr.js@1.9.0:
|
||||
ipaddr.js@1.9.0, ipaddr.js@^1.9.0:
|
||||
version "1.9.0"
|
||||
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.0.tgz#37df74e430a0e47550fe54a2defe30d8acd95f65"
|
||||
integrity sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==
|
||||
|
||||
ipaddr.js@^1.9.0:
|
||||
version "1.9.1"
|
||||
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3"
|
||||
integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==
|
||||
|
||||
is-accessor-descriptor@^0.1.6:
|
||||
version "0.1.6"
|
||||
resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6"
|
||||
@ -1918,9 +1901,9 @@ is-number@^7.0.0:
|
||||
integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
|
||||
|
||||
is-path-cwd@^2.0.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb"
|
||||
integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.1.0.tgz#2e0c7e463ff5b7a0eb60852d851a6809347a124c"
|
||||
integrity sha512-Sc5j3/YnM8tDeyCsVeKlm/0p95075DyLmDEIkSgQ7mXkrOX+uTCtmQFm0CYzVyJwcCCmO3k8qfJt17SxQwB5Zw==
|
||||
|
||||
is-path-in-cwd@^2.0.0:
|
||||
version "2.1.0"
|
||||
@ -1936,7 +1919,7 @@ is-path-inside@^2.1.0:
|
||||
dependencies:
|
||||
path-is-inside "^1.0.2"
|
||||
|
||||
is-plain-object@^2.0.3, is-plain-object@^2.0.4:
|
||||
is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677"
|
||||
integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==
|
||||
@ -2043,7 +2026,7 @@ loader-runner@^2.3.0:
|
||||
resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357"
|
||||
integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==
|
||||
|
||||
loader-utils@1.2.3, loader-utils@^1.0.2, loader-utils@^1.1.0:
|
||||
loader-utils@1.2.3, loader-utils@^1.0.2, loader-utils@^1.1.0, loader-utils@^1.2.3:
|
||||
version "1.2.3"
|
||||
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.2.3.tgz#1ff5dc6911c9f0a062531a4c04b609406108c2c7"
|
||||
integrity sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==
|
||||
@ -2061,9 +2044,9 @@ locate-path@^3.0.0:
|
||||
path-exists "^3.0.0"
|
||||
|
||||
lodash@^4.17.11:
|
||||
version "4.17.15"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
|
||||
integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
|
||||
version "4.17.11"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d"
|
||||
integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==
|
||||
|
||||
loglevel@^1.6.3:
|
||||
version "1.6.3"
|
||||
@ -2271,9 +2254,9 @@ mississippi@^3.0.0:
|
||||
through2 "^2.0.0"
|
||||
|
||||
mixin-deep@^1.2.0:
|
||||
version "1.3.2"
|
||||
resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566"
|
||||
integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.1.tgz#a49e7268dce1a0d9698e45326c5626df3543d0fe"
|
||||
integrity sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==
|
||||
dependencies:
|
||||
for-in "^1.0.2"
|
||||
is-extendable "^1.0.1"
|
||||
@ -2447,9 +2430,9 @@ npm-bundled@^1.0.1:
|
||||
integrity sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g==
|
||||
|
||||
npm-packlist@^1.1.6:
|
||||
version "1.4.4"
|
||||
resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.4.tgz#866224233850ac534b63d1a6e76050092b5d2f44"
|
||||
integrity sha512-zTLo8UcVYtDU3gdeaFu2Xu0n0EvelfHDGuqtNIn5RO7yQj4H1TqNdBc/yZjxnWA0PVB8D3Woyp0i5B43JwQ6Vw==
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.1.tgz#19064cdf988da80ea3cee45533879d90192bbfbc"
|
||||
integrity sha512-+TcdO7HJJ8peiiYhvPxsEDhF3PJFGUGRcFsGve3vxvxdcpO2Z4Z7rkosRM0kWj6LfbK/P0gu3dzk5RU1ffvFcw==
|
||||
dependencies:
|
||||
ignore-walk "^3.0.1"
|
||||
npm-bundled "^1.0.1"
|
||||
@ -2742,9 +2725,9 @@ pkg-dir@^3.0.0:
|
||||
find-up "^3.0.0"
|
||||
|
||||
portfinder@^1.0.20:
|
||||
version "1.0.21"
|
||||
resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.21.tgz#60e1397b95ac170749db70034ece306b9a27e324"
|
||||
integrity sha512-ESabpDCzmBS3ekHbmpAIiESq3udRsCBGiBZLsC+HgBKv2ezb0R4oG+7RnYEVZ/ZCfhel5Tx3UzdNWA0Lox2QCA==
|
||||
version "1.0.20"
|
||||
resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.20.tgz#bea68632e54b2e13ab7b0c4775e9b41bf270e44a"
|
||||
integrity sha512-Yxe4mTyDzTd59PZJY4ojZR8F+E5e97iq2ZOHPz3HDgSvYC5siNad2tLooQ5y5QHyQhc3xVqvyk/eNA3wuoa7Sw==
|
||||
dependencies:
|
||||
async "^1.5.2"
|
||||
debug "^2.2.0"
|
||||
@ -3031,16 +3014,11 @@ run-queue@^1.0.0, run-queue@^1.0.3:
|
||||
dependencies:
|
||||
aproba "^1.1.1"
|
||||
|
||||
safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
|
||||
safe-buffer@5.1.2, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
|
||||
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
|
||||
|
||||
safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519"
|
||||
integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==
|
||||
|
||||
safe-regex@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e"
|
||||
@ -3085,9 +3063,9 @@ semver@^5.3.0, semver@^5.5.0, semver@^5.6.0:
|
||||
integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==
|
||||
|
||||
semver@^6.0.0, semver@^6.1.1:
|
||||
version "6.3.0"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
|
||||
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
|
||||
version "6.1.2"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-6.1.2.tgz#079960381376a3db62eb2edc8a3bfb10c7cfe318"
|
||||
integrity sha512-z4PqiCpomGtWj8633oeAdXm1Kn1W++3T8epkZYnwiVgIYIJ0QHszhInYSJTYxebByQH7KVCEAn8R9duzZW2PhQ==
|
||||
|
||||
send@0.17.1:
|
||||
version "0.17.1"
|
||||
@ -3141,10 +3119,20 @@ set-blocking@^2.0.0, set-blocking@~2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
|
||||
integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc=
|
||||
|
||||
set-value@^2.0.0, set-value@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b"
|
||||
integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==
|
||||
set-value@^0.4.3:
|
||||
version "0.4.3"
|
||||
resolved "https://registry.yarnpkg.com/set-value/-/set-value-0.4.3.tgz#7db08f9d3d22dc7f78e53af3c3bf4666ecdfccf1"
|
||||
integrity sha1-fbCPnT0i3H945Trzw79GZuzfzPE=
|
||||
dependencies:
|
||||
extend-shallow "^2.0.1"
|
||||
is-extendable "^0.1.1"
|
||||
is-plain-object "^2.0.1"
|
||||
to-object-path "^0.3.0"
|
||||
|
||||
set-value@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.0.tgz#71ae4a88f0feefbbf52d1ea604f3fb315ebb6274"
|
||||
integrity sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==
|
||||
dependencies:
|
||||
extend-shallow "^2.0.1"
|
||||
is-extendable "^0.1.1"
|
||||
@ -3257,10 +3245,10 @@ source-map-resolve@^0.5.0:
|
||||
source-map-url "^0.4.0"
|
||||
urix "^0.1.0"
|
||||
|
||||
source-map-support@~0.5.12:
|
||||
version "0.5.13"
|
||||
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932"
|
||||
integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==
|
||||
source-map-support@~0.5.10:
|
||||
version "0.5.12"
|
||||
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.12.tgz#b4f3b10d51857a5af0138d3ce8003b201613d599"
|
||||
integrity sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==
|
||||
dependencies:
|
||||
buffer-from "^1.0.0"
|
||||
source-map "^0.6.0"
|
||||
@ -3293,9 +3281,9 @@ spdy-transport@^3.0.0:
|
||||
wbuf "^1.7.3"
|
||||
|
||||
spdy@^4.0.0:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/spdy/-/spdy-4.0.1.tgz#6f12ed1c5db7ea4f24ebb8b89ba58c87c08257f2"
|
||||
integrity sha512-HeZS3PBdMA+sZSu0qwpCxl3DeALD5ASx8pAX0jZdKXSpPWbQ6SYGnlg3BBmYLx5LtiZrmkAZfErCm2oECBcioA==
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/spdy/-/spdy-4.0.0.tgz#81f222b5a743a329aa12cea6a390e60e9b613c52"
|
||||
integrity sha512-ot0oEGT/PGUpzf/6uk4AWLqkq+irlqHXkrdbk51oWONh3bxQmBuljxPNl66zlRRcIJStWq0QkLUCPOPjgjvU0Q==
|
||||
dependencies:
|
||||
debug "^4.1.0"
|
||||
handle-thing "^2.0.0"
|
||||
@ -3466,28 +3454,29 @@ tar@^4:
|
||||
yallist "^3.0.3"
|
||||
|
||||
terser-webpack-plugin@^1.1.0:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.1.tgz#61b18e40eaee5be97e771cdbb10ed1280888c2b4"
|
||||
integrity sha512-ZXmmfiwtCLfz8WKZyYUuuHf3dMYEjg8NrjHMb0JqHVHVOSkzp3cW2/XG1fP3tRhqEqSzMwzzRQGtAPbs4Cncxg==
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.3.0.tgz#69aa22426299f4b5b3775cbed8cb2c5d419aa1d4"
|
||||
integrity sha512-W2YWmxPjjkUcOWa4pBEv4OP4er1aeQJlSo2UhtCFQCuRXEHjOFscO8VyWHj9JLlA0RzQb8Y2/Ta78XZvT54uGg==
|
||||
dependencies:
|
||||
cacache "^12.0.2"
|
||||
find-cache-dir "^2.1.0"
|
||||
cacache "^11.3.2"
|
||||
find-cache-dir "^2.0.0"
|
||||
is-wsl "^1.1.0"
|
||||
loader-utils "^1.2.3"
|
||||
schema-utils "^1.0.0"
|
||||
serialize-javascript "^1.7.0"
|
||||
source-map "^0.6.1"
|
||||
terser "^4.1.2"
|
||||
webpack-sources "^1.4.0"
|
||||
terser "^4.0.0"
|
||||
webpack-sources "^1.3.0"
|
||||
worker-farm "^1.7.0"
|
||||
|
||||
terser@^4.1.2:
|
||||
version "4.1.2"
|
||||
resolved "https://registry.yarnpkg.com/terser/-/terser-4.1.2.tgz#b2656c8a506f7ce805a3f300a2ff48db022fa391"
|
||||
integrity sha512-jvNoEQSPXJdssFwqPSgWjsOrb+ELoE+ILpHPKXC83tIxOlh2U75F1KuB2luLD/3a6/7K3Vw5pDn+hvu0C4AzSw==
|
||||
terser@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/terser/-/terser-4.0.0.tgz#ef356f6f359a963e2cc675517f21c1c382877374"
|
||||
integrity sha512-dOapGTU0hETFl1tCo4t56FN+2jffoKyER9qBGoUFyZ6y7WLoKT0bF+lAYi6B6YsILcGF3q1C2FBh8QcKSCgkgA==
|
||||
dependencies:
|
||||
commander "^2.20.0"
|
||||
commander "^2.19.0"
|
||||
source-map "~0.6.1"
|
||||
source-map-support "~0.5.12"
|
||||
source-map-support "~0.5.10"
|
||||
|
||||
through2@^2.0.0:
|
||||
version "2.0.5"
|
||||
@ -3585,20 +3574,20 @@ typedarray@^0.0.6:
|
||||
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
|
||||
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
|
||||
|
||||
typescript@3.5.3:
|
||||
version "3.5.3"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.5.3.tgz#c830f657f93f1ea846819e929092f5fe5983e977"
|
||||
integrity sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g==
|
||||
typescript@3.5.2:
|
||||
version "3.5.2"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.5.2.tgz#a09e1dc69bc9551cadf17dba10ee42cf55e5d56c"
|
||||
integrity sha512-7KxJovlYhTX5RaRbUdkAXN1KUZ8PwWlTzQdHV6xNqvuFOs7+WBo10TQUqT19Q/Jz2hk5v9TQDIhyLhhJY4p5AA==
|
||||
|
||||
union-value@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847"
|
||||
integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4"
|
||||
integrity sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=
|
||||
dependencies:
|
||||
arr-union "^3.1.0"
|
||||
get-value "^2.0.6"
|
||||
is-extendable "^0.1.1"
|
||||
set-value "^2.0.1"
|
||||
set-value "^0.4.3"
|
||||
|
||||
unique-filename@^1.1.1:
|
||||
version "1.1.1"
|
||||
@ -3725,10 +3714,10 @@ wbuf@^1.1.0, wbuf@^1.7.3:
|
||||
dependencies:
|
||||
minimalistic-assert "^1.0.0"
|
||||
|
||||
webpack-cli@^3.3.6:
|
||||
version "3.3.6"
|
||||
resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.3.6.tgz#2c8c399a2642133f8d736a359007a052e060032c"
|
||||
integrity sha512-0vEa83M7kJtxK/jUhlpZ27WHIOndz5mghWL2O53kiDoA9DIxSKnfqB92LoqEn77cT4f3H2cZm1BMEat/6AZz3A==
|
||||
webpack-cli@^3.3.5:
|
||||
version "3.3.5"
|
||||
resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.3.5.tgz#f4d1238a66a2843d9cebf189835ea22142e72767"
|
||||
integrity sha512-w0j/s42c5UhchwTmV/45MLQnTVwRoaUTu9fM5LuyOd/8lFoCNCELDogFoecx5NzRUndO0yD/gF2b02XKMnmAWQ==
|
||||
dependencies:
|
||||
chalk "2.4.2"
|
||||
cross-spawn "6.0.5"
|
||||
@ -3797,24 +3786,25 @@ webpack-log@^2.0.0:
|
||||
ansi-colors "^3.0.0"
|
||||
uuid "^3.3.2"
|
||||
|
||||
webpack-sources@^1.3.0, webpack-sources@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.0.tgz#be93d629601aa3ea48e8686ee4d78d9c4e706061"
|
||||
integrity sha512-1e4Cxgqfl8vnDhXMMpegX7JWWP7HwV8Kp8/Oefs6EG52bRtOR9vuOXM1Gl1vy6NwHfUxHeuR6ElD4HamuRPO0A==
|
||||
webpack-sources@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.3.0.tgz#2a28dcb9f1f45fe960d8f1493252b5ee6530fa85"
|
||||
integrity sha512-OiVgSrbGu7NEnEvQJJgdSFPl2qWKkWq5lHMhgiToIiN9w34EBnjYzSYs+VbL5KoYiLNtFFa7BZIKxRED3I32pA==
|
||||
dependencies:
|
||||
source-list-map "^2.0.0"
|
||||
source-map "~0.6.1"
|
||||
|
||||
webpack@4.38.0:
|
||||
version "4.38.0"
|
||||
resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.38.0.tgz#6d77108404b08883c78f4e7e45a43c4e5c47c931"
|
||||
integrity sha512-lbuFsVOq8PZY+1Ytz/mYOvYOo+d4IJ31hHk/7iyoeWtwN33V+5HYotSH+UIb9tq914ey0Hot7z6HugD+je3sWw==
|
||||
webpack@4.35.0:
|
||||
version "4.35.0"
|
||||
resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.35.0.tgz#ad3f0f8190876328806ccb7a36f3ce6e764b8378"
|
||||
integrity sha512-M5hL3qpVvtr8d4YaJANbAQBc4uT01G33eDpl/psRTBCfjxFTihdhin1NtAKB1ruDwzeVdcsHHV3NX+QsAgOosw==
|
||||
dependencies:
|
||||
"@webassemblyjs/ast" "1.8.5"
|
||||
"@webassemblyjs/helper-module-context" "1.8.5"
|
||||
"@webassemblyjs/wasm-edit" "1.8.5"
|
||||
"@webassemblyjs/wasm-parser" "1.8.5"
|
||||
acorn "^6.2.0"
|
||||
acorn "^6.0.5"
|
||||
acorn-dynamic-import "^4.0.0"
|
||||
ajv "^6.1.0"
|
||||
ajv-keywords "^3.1.0"
|
||||
chrome-trace-event "^1.0.0"
|
||||
@ -3897,9 +3887,9 @@ wrappy@1:
|
||||
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
|
||||
|
||||
xtend@^4.0.0, xtend@~4.0.1:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
|
||||
integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"
|
||||
integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68=
|
||||
|
||||
"y18n@^3.2.1 || ^4.0.0", y18n@^4.0.0:
|
||||
version "4.0.0"
|
||||
|
||||
1189
Website/package-lock.json
generated
1189
Website/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -12,25 +12,25 @@
|
||||
"author": "serushakov",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.5.5",
|
||||
"@babel/core": "^7.5.5",
|
||||
"@babel/preset-env": "^7.5.5",
|
||||
"@babel/cli": "^7.4.0",
|
||||
"@babel/core": "^7.4.0",
|
||||
"@babel/preset-env": "^7.4.5",
|
||||
"babel-loader": "^8.0.6",
|
||||
"css-loader": "^3.1.0",
|
||||
"css-loader": "^3.0.0",
|
||||
"extract-text-webpack-plugin": "4.0.0-alpha.0",
|
||||
"file-loader": "^4.1.0",
|
||||
"file-loader": "^4.0.0",
|
||||
"html-webpack-plugin": "3.2.0",
|
||||
"mini-css-extract-plugin": "0.8.0",
|
||||
"mini-css-extract-plugin": "0.7.0",
|
||||
"node-sass": "4.12.0",
|
||||
"prettier": "1.18.2",
|
||||
"sass-loader": "7.1.0",
|
||||
"style-loader": "0.23.1",
|
||||
"webpack": "4.38.0",
|
||||
"webpack-cli": "3.3.6",
|
||||
"webpack": "4.34.0",
|
||||
"webpack-cli": "3.3.4",
|
||||
"webpack-dev-server": "3.7.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "7.5.5",
|
||||
"@babel/runtime": "7.4.5",
|
||||
"smoothscroll-polyfill": "0.4.4",
|
||||
"velocity-animate": "1.5.2"
|
||||
}
|
||||
|
||||
@ -45,7 +45,7 @@
|
||||
<button class="button" id="get-started">
|
||||
Get started
|
||||
</button>
|
||||
<a class="link" href="https://wolt.com/blog/hq/2019/07/01/how-we-came-to-create-a-new-image-placeholder-algorithm-blurhash/">
|
||||
<a class="link" href="#">
|
||||
More on our blog
|
||||
</a>
|
||||
</div>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user