initial commit
This commit is contained in:
17
.eslintrc.js
Normal file
17
.eslintrc.js
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
module.exports = {
|
||||||
|
root: true,
|
||||||
|
env: {
|
||||||
|
node: true
|
||||||
|
},
|
||||||
|
'extends': [
|
||||||
|
'plugin:vue/essential',
|
||||||
|
'eslint:recommended'
|
||||||
|
],
|
||||||
|
parserOptions: {
|
||||||
|
parser: 'babel-eslint'
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
|
||||||
|
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
|
||||||
|
}
|
||||||
|
}
|
||||||
21
.gitignore
vendored
Normal file
21
.gitignore
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
.DS_Store
|
||||||
|
node_modules
|
||||||
|
/dist
|
||||||
|
|
||||||
|
# local env files
|
||||||
|
.env.local
|
||||||
|
.env.*.local
|
||||||
|
|
||||||
|
# Log files
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.idea
|
||||||
|
.vscode
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
||||||
1
.purs-repl
Normal file
1
.purs-repl
Normal file
@@ -0,0 +1 @@
|
|||||||
|
import Prelude
|
||||||
18
README.md
18
README.md
@@ -1,2 +1,18 @@
|
|||||||
# pure-vue
|
# pure-vue
|
||||||
Vue.js Purescript binding using Composition API
|
|
||||||
|
## Project setup
|
||||||
|
```
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
### Compiles and hot-reloads for development
|
||||||
|
1. spago install arrays
|
||||||
|
3. spago install record-extra
|
||||||
|
1. vue create my_cool_project
|
||||||
|
2. cd my_cool_project
|
||||||
|
3. spago init
|
||||||
|
4. npm install vue-cli-plugin-pure-vue
|
||||||
|
5. vue invoke vue-cli-plugin-pure-vue
|
||||||
|
|
||||||
|
## Example Application
|
||||||
|
Check out Todo List [Example Application](https://https://github.com/smarwei/pure-vue-todo-example).
|
||||||
|
|||||||
34
generator/index.js
Normal file
34
generator/index.js
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
module.exports = (api, options) => {
|
||||||
|
api.render('./templateExampleApp')
|
||||||
|
if(options.createVueConfigJs.toLowerCase() === 'y') {
|
||||||
|
api.render('./template')
|
||||||
|
}
|
||||||
|
|
||||||
|
api.extendPackage({
|
||||||
|
dependencies: {
|
||||||
|
'@vue/composition-api': '^0.5.0'
|
||||||
|
},
|
||||||
|
devDependencies: {
|
||||||
|
"purs-loader": "^3.7.1"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
api.injectImports(api.entryFile, `import VueCompositionApi from '@vue/composition-api'`)
|
||||||
|
|
||||||
|
module.exports.hooks = (api) => {
|
||||||
|
api.afterInvoke(() => {
|
||||||
|
const { EOL } = require('os')
|
||||||
|
const fs = require('fs')
|
||||||
|
const contentMain = fs.readFileSync(api.resolve(api.entryFile), { encoding: 'utf-8' })
|
||||||
|
const lines = contentMain.split(/\r?\n/g).reverse()
|
||||||
|
|
||||||
|
if (lines.findIndex(line => line.match(/Vue\.use.*VueCompositionApi.*/)) !== -1) return
|
||||||
|
|
||||||
|
const renderIndex = lines.findIndex(line => line.match(/import/))
|
||||||
|
lines[renderIndex-1] += `${EOL}Vue.use(VueCompositionApi);${EOL}`
|
||||||
|
lines.reverse()
|
||||||
|
|
||||||
|
fs.writeFileSync(api.entryFile, lines.join(EOL), { encoding: 'utf-8' })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
16
generator/template/spago.dhall
Normal file
16
generator/template/spago.dhall
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
{-
|
||||||
|
Welcome to a Spago project!
|
||||||
|
You can edit this file as you like.
|
||||||
|
-}
|
||||||
|
{ name = "my-project"
|
||||||
|
, dependencies =
|
||||||
|
[ "arrays"
|
||||||
|
, "console"
|
||||||
|
, "effect"
|
||||||
|
, "psci-support"
|
||||||
|
, "record-extra"
|
||||||
|
, "typelevel-prelude"
|
||||||
|
]
|
||||||
|
, packages = ./packages.dhall
|
||||||
|
, sources = [ "src/**/*.purs", "node_modules/vue-cli-plugin-pure-vue/src/**/*.purs", "test/**/*.purs" ]
|
||||||
|
}
|
||||||
21
generator/template/vue.config.js
Normal file
21
generator/template/vue.config.js
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
chainWebpack: config => {
|
||||||
|
// Purescript Loader
|
||||||
|
config.module
|
||||||
|
.rule('purescript')
|
||||||
|
.test(/\.purs$/)
|
||||||
|
.use('purs-loader')
|
||||||
|
.loader('purs-loader')
|
||||||
|
.tap(() => ({
|
||||||
|
// bundle: true,
|
||||||
|
// spago: true,
|
||||||
|
src: [
|
||||||
|
path.join('src', '**', '*.purs'),
|
||||||
|
path.join('node_modules', 'vue-cli-plugin-pure-vue', 'src', '**', '*.purs'),
|
||||||
|
path.join('.spago', '**', 'src', '**', '*.purs'),
|
||||||
|
],
|
||||||
|
}))
|
||||||
|
},
|
||||||
|
}
|
||||||
52
generator/templateExampleApp/src/App.purs
Normal file
52
generator/templateExampleApp/src/App.purs
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
module App where
|
||||||
|
|
||||||
|
import Prelude
|
||||||
|
import Effect (Effect)
|
||||||
|
import Effect.Unsafe (unsafePerformEffect)
|
||||||
|
import Effect.Vue.Ref as Ref
|
||||||
|
import Effect.Vue.Hooks as Hooks
|
||||||
|
import Effect.Class.Console (logShow)
|
||||||
|
import Data.Array (snoc)
|
||||||
|
|
||||||
|
|
||||||
|
type Product = { id :: Int, title :: String, price :: Number }
|
||||||
|
createProduct :: Array Product -> Int -> String -> Number -> Array Product
|
||||||
|
createProduct products id title price = snoc products { id, title, price }
|
||||||
|
|
||||||
|
execCreateProduct :: Ref.Ref (Array Product) -> String -> Number -> Effect Unit
|
||||||
|
execCreateProduct products title price = do
|
||||||
|
p <- Ref.read products
|
||||||
|
let p' = createProduct p 42 title (23.666)
|
||||||
|
Ref.write p' products
|
||||||
|
|
||||||
|
incRelease :: Ref.Ref Int -> Effect Unit
|
||||||
|
incRelease release = Ref.modify_ (\x -> x + 1) release
|
||||||
|
|
||||||
|
compTest :: Ref.Ref Int -> Effect Int
|
||||||
|
compTest release = do
|
||||||
|
r <- Ref.read release
|
||||||
|
pure (r + 1)
|
||||||
|
|
||||||
|
type Props = {}
|
||||||
|
|
||||||
|
setup :: forall a. Props -> Effect a
|
||||||
|
setup props = unsafePerformEffect do
|
||||||
|
products :: Ref.Ref (Array Product) <- Ref.new []
|
||||||
|
showUserInfo <- Ref.new false
|
||||||
|
release <- Ref.new 9
|
||||||
|
|
||||||
|
computedTest <- Ref.computed $ compTest release
|
||||||
|
|
||||||
|
Hooks.onMounted mounted
|
||||||
|
|
||||||
|
Ref.vReturn { products
|
||||||
|
, showUserInfo
|
||||||
|
, release
|
||||||
|
, computedTest
|
||||||
|
, incRelease: (incRelease release)
|
||||||
|
, addProduct: (execCreateProduct products)
|
||||||
|
}
|
||||||
|
|
||||||
|
mounted :: Effect Unit
|
||||||
|
mounted = do
|
||||||
|
logShow "estasetase"
|
||||||
31
generator/templateExampleApp/src/App.vue
Normal file
31
generator/templateExampleApp/src/App.vue
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<button
|
||||||
|
target="_blank"
|
||||||
|
@click="incRelease(); addProduct('mytit')(32)();"
|
||||||
|
/>
|
||||||
|
<span class="mr-2">Latest Release {{ release }}</span>
|
||||||
|
|
||||||
|
ctest - {{ computedTest }} -
|
||||||
|
<privacy-policy
|
||||||
|
:release="42"
|
||||||
|
></privacy-policy>
|
||||||
|
<!--router-view
|
||||||
|
:release="release"
|
||||||
|
></router-view-->
|
||||||
|
{{ products }}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { setup } from '@/App.purs'
|
||||||
|
import PrivacyPolicy from './views/PrivacyPolicy'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'App',
|
||||||
|
components: {
|
||||||
|
PrivacyPolicy,
|
||||||
|
},
|
||||||
|
setup
|
||||||
|
};
|
||||||
|
</script>
|
||||||
24
generator/templateExampleApp/src/views/PrivacyPolicy.purs
Normal file
24
generator/templateExampleApp/src/views/PrivacyPolicy.purs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
module PrivacyPolicy where
|
||||||
|
|
||||||
|
import Prelude
|
||||||
|
import Effect (Effect)
|
||||||
|
import Effect.Unsafe (unsafePerformEffect)
|
||||||
|
import Effect.Vue.Ref as Ref
|
||||||
|
import Record.Extra as Record
|
||||||
|
import Data.Array as Arr
|
||||||
|
import Type.Row (RProxy(..))
|
||||||
|
|
||||||
|
type Props = ( release :: Int )
|
||||||
|
|
||||||
|
-- this to lib
|
||||||
|
-- type RecordProps = Record.Record Props
|
||||||
|
props = Record.keys (RProxy :: RProxy Props)
|
||||||
|
|
||||||
|
privacyPolicy :: String -> String
|
||||||
|
privacyPolicy policyRaw = policyRaw
|
||||||
|
|
||||||
|
buildSetup :: forall a. String -> _ -> Effect a
|
||||||
|
buildSetup policyRaw props = unsafePerformEffect do
|
||||||
|
dialog <- Ref.new true
|
||||||
|
|
||||||
|
Ref.vReturn { dialog, privacyPolicy: privacyPolicy policyRaw }
|
||||||
31
generator/templateExampleApp/src/views/PrivacyPolicy.vue
Normal file
31
generator/templateExampleApp/src/views/PrivacyPolicy.vue
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<template>
|
||||||
|
<v-container>
|
||||||
|
<v-layout>
|
||||||
|
<v-card>
|
||||||
|
<v-card-title
|
||||||
|
class="headline grey lighten-2"
|
||||||
|
primary-title
|
||||||
|
>
|
||||||
|
Privacy Policy r {{ release }}
|
||||||
|
</v-card-title>
|
||||||
|
|
||||||
|
<v-card-text v-html="privacyPolicy()">
|
||||||
|
</v-card-text>
|
||||||
|
</v-card>
|
||||||
|
</v-layout>
|
||||||
|
</v-container>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { buildSetup, props } from '@/views/PrivacyPolicy.purs'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'PrivacyPolicy',
|
||||||
|
props,
|
||||||
|
setup: buildSetup('myprvipolicy'),
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
|
||||||
|
</style>
|
||||||
20
package.json
Normal file
20
package.json
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"name": "vue-cli-plugin-pure-vue",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"description": "Purescript bindings for Vue.js using Compsition API",
|
||||||
|
"license": "Unlicense",
|
||||||
|
"repository": "smweiss/pure-vue",
|
||||||
|
"main": "index.js",
|
||||||
|
"keywords": [
|
||||||
|
"vue.js",
|
||||||
|
"vue",
|
||||||
|
"purescript",
|
||||||
|
"binding",
|
||||||
|
"smweiss"
|
||||||
|
],
|
||||||
|
"private": true,
|
||||||
|
"dependencies": {
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
}
|
||||||
|
}
|
||||||
9
prompts.js
Normal file
9
prompts.js
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
module.exports = [
|
||||||
|
{
|
||||||
|
type: 'input',
|
||||||
|
name: 'createVueConfigJs',
|
||||||
|
message: 'Create vue.config.js (overrides if already existing)',
|
||||||
|
validate: input => ['Y', 'y', 'N', 'n'].includes(input),
|
||||||
|
default: 'Y'
|
||||||
|
},
|
||||||
|
]
|
||||||
28
src/Props.purs
Normal file
28
src/Props.purs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
module Props where
|
||||||
|
|
||||||
|
import Prelude
|
||||||
|
|
||||||
|
|
||||||
|
type Props = Array PropType
|
||||||
|
data PropType = Int String
|
||||||
|
| String String
|
||||||
|
| Number String
|
||||||
|
-- | Object String
|
||||||
|
|
||||||
|
toProp :: PropType -> String
|
||||||
|
toProp (Int s) = s
|
||||||
|
toProp (String s) = s
|
||||||
|
toProp (Number s) = s
|
||||||
|
|
||||||
|
toProps :: Array PropType -> Array String
|
||||||
|
toProps = map toProp
|
||||||
|
|
||||||
|
|
||||||
|
-- class Proppable a where
|
||||||
|
-- toProps :: a -> Array String
|
||||||
|
--
|
||||||
|
-- --instance propProps :: Proppable Props
|
||||||
|
-- -- toProps p = Arr.fromFoldable $ Record.keys (RProxy :: RProxy Props)
|
||||||
|
--
|
||||||
|
-- type PropsRecord = Record Props
|
||||||
|
-- props = Arr.fromFoldable $ Record.keys (RProxy :: RProxy Props)
|
||||||
50
src/vueHooks.js
Normal file
50
src/vueHooks.js
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
var comp = require("@vue/composition-api");
|
||||||
|
|
||||||
|
// exports.onMounted = vue.onMounted
|
||||||
|
exports.onBeforeMount = function(eff) {
|
||||||
|
return function() {
|
||||||
|
comp.on(eff)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.onMounted = function(eff) {
|
||||||
|
return function() {
|
||||||
|
comp.onMounted(eff)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.onBeforeUpdate = function(eff) {
|
||||||
|
return function() {
|
||||||
|
comp.on(eff)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.onUpdated = function(eff) {
|
||||||
|
return function() {
|
||||||
|
comp.on(eff)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.onBeforeUnmount = function(eff) {
|
||||||
|
return function() {
|
||||||
|
comp.on(eff)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.onUnmounted = function(eff) {
|
||||||
|
return function() {
|
||||||
|
comp.on(eff)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.onActivated = function(eff) {
|
||||||
|
return function() {
|
||||||
|
comp.on(eff)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.onDeactivated = function(eff) {
|
||||||
|
return function() {
|
||||||
|
comp.on(eff)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.onErrorCaptured = function(eff) {
|
||||||
|
return function() {
|
||||||
|
comp.on(eff)
|
||||||
|
}
|
||||||
|
}
|
||||||
35
src/vueHooks.purs
Normal file
35
src/vueHooks.purs
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
module Effect.Vue.Hooks
|
||||||
|
( onBeforeMount
|
||||||
|
, onMounted
|
||||||
|
, onBeforeUpdate
|
||||||
|
, onUpdated
|
||||||
|
, onBeforeUnmount
|
||||||
|
, onUnmounted
|
||||||
|
, onActivated
|
||||||
|
, onDeactivated
|
||||||
|
, onErrorCaptured
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Prelude
|
||||||
|
import Effect (Effect)
|
||||||
|
import Effect.Class (class MonadEffect, liftEffect)
|
||||||
|
|
||||||
|
-- These lifecycle registration methods can only be used during the invocation of a setup hook.
|
||||||
|
-- It automatically figures out the current instance calling the setup hook using internal global state.
|
||||||
|
-- It is intentionally designed this way to reduce friction when extracting logic into external functions.
|
||||||
|
|
||||||
|
-- foreign import onMounted :: forall m a. MonadEffect m => a -> m Unit
|
||||||
|
foreign import onBeforeMount :: Effect Unit -> Effect Unit
|
||||||
|
foreign import onMounted :: Effect Unit -> Effect Unit
|
||||||
|
foreign import onBeforeUpdate :: Effect Unit -> Effect Unit
|
||||||
|
foreign import onUpdated :: Effect Unit -> Effect Unit
|
||||||
|
foreign import onBeforeUnmount :: Effect Unit -> Effect Unit
|
||||||
|
foreign import onUnmounted :: Effect Unit -> Effect Unit
|
||||||
|
foreign import onActivated :: Effect Unit -> Effect Unit
|
||||||
|
foreign import onDeactivated :: Effect Unit -> Effect Unit
|
||||||
|
foreign import onErrorCaptured :: Effect Unit -> Effect Unit
|
||||||
|
|
||||||
|
-- What about
|
||||||
|
-- onRenderTracked
|
||||||
|
-- onRenderTriggered
|
||||||
|
-- ?
|
||||||
57
src/vueRef.js
Normal file
57
src/vueRef.js
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
var comp = require("@vue/composition-api");
|
||||||
|
|
||||||
|
// Ref
|
||||||
|
|
||||||
|
exports.vReturn = function(dict) {
|
||||||
|
return function() {
|
||||||
|
return dict
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.new = function (val) {
|
||||||
|
return function () {
|
||||||
|
return comp.ref(val);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.read = function (ref) {
|
||||||
|
return function () {
|
||||||
|
return ref.value;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.modifyImpl = function (f) {
|
||||||
|
return function (ref) {
|
||||||
|
return function () {
|
||||||
|
var t = f(ref.value);
|
||||||
|
ref.value = t.state;
|
||||||
|
return t.value;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.write = function (val) {
|
||||||
|
return function (ref) {
|
||||||
|
return function () {
|
||||||
|
ref.value = val;
|
||||||
|
return {};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Computed
|
||||||
|
|
||||||
|
exports.computed = function (fn) {
|
||||||
|
return function () {
|
||||||
|
return comp.computed(fn)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// to seperate module
|
||||||
|
|
||||||
|
// exports.setup = function (props) {
|
||||||
|
// }
|
||||||
57
src/vueRef.purs
Normal file
57
src/vueRef.purs
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
module Effect.Vue.Ref
|
||||||
|
( Ref
|
||||||
|
, new
|
||||||
|
, read
|
||||||
|
, modify'
|
||||||
|
, modify
|
||||||
|
, modify_
|
||||||
|
, write
|
||||||
|
, vReturn
|
||||||
|
, computed
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Prelude
|
||||||
|
import Effect (Effect)
|
||||||
|
|
||||||
|
-- data Ref a = Ref a
|
||||||
|
-- foreign import ref :: forall a b. a -> Ref b
|
||||||
|
-- foreign import refVal :: forall a b. Ref a -> a
|
||||||
|
|
||||||
|
|
||||||
|
foreign import vReturn :: forall a b. a -> Effect b
|
||||||
|
|
||||||
|
|
||||||
|
-- | A value of type `Ref a` represents a mutable reference
|
||||||
|
-- | which holds a value of type `a`.
|
||||||
|
foreign import data Ref :: Type -> Type
|
||||||
|
|
||||||
|
-- | Create a new mutable reference containing the specified value.
|
||||||
|
foreign import new :: forall s. s -> Effect (Ref s)
|
||||||
|
|
||||||
|
-- | Read the current value of a mutable reference
|
||||||
|
foreign import read :: forall s. Ref s -> Effect s
|
||||||
|
|
||||||
|
-- | Update the value of a mutable reference by applying a function
|
||||||
|
-- | to the current value.
|
||||||
|
modify' :: forall s b. (s -> { state :: s, value :: b }) -> Ref s -> Effect b
|
||||||
|
modify' = modifyImpl
|
||||||
|
|
||||||
|
foreign import modifyImpl :: forall s b. (s -> { state :: s, value :: b }) -> Ref s -> Effect b
|
||||||
|
|
||||||
|
-- | Update the value of a mutable reference by applying a function
|
||||||
|
-- | to the current value. The updated value is returned.
|
||||||
|
modify :: forall s. (s -> s) -> Ref s -> Effect s
|
||||||
|
modify f = modify' \s -> let s' = f s in { state: s', value: s' }
|
||||||
|
|
||||||
|
modify_ :: forall s. (s -> s) -> Ref s -> Effect Unit
|
||||||
|
modify_ f s = void $ modify f s
|
||||||
|
|
||||||
|
-- | Update the value of a mutable reference to the specified value.
|
||||||
|
foreign import write :: forall s. s -> Ref s -> Effect Unit
|
||||||
|
|
||||||
|
|
||||||
|
-- |
|
||||||
|
-- | COMPUTED
|
||||||
|
-- |
|
||||||
|
|
||||||
|
foreign import computed :: forall a b. Effect a -> Effect (Ref b)
|
||||||
7
workspace.code-workspace
Normal file
7
workspace.code-workspace
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"folders": [
|
||||||
|
{
|
||||||
|
"path": "."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user