Compare commits

...

9 Commits

Author SHA1 Message Date
Johann150 80dddeea02
enhance page editor
Using a plain textarea looks ugly and it is very small by default. Using
a MkTextarea fixes this.

For the readonly view, the individual fields should respectively be readonly.
2022-08-04 00:16:17 +02:00
Johann150 b7b3ea3bed
backend: fix packing pages 2022-08-03 23:38:05 +02:00
Johann150 5f6a6f4607
fix router for new page editor path 2022-08-03 23:04:16 +02:00
Johann150 2a68ea808a
add best effort migration for pages 2022-08-01 10:55:12 +02:00
Johann150 3567c515de
client: siplify page display 2022-08-01 08:34:25 +02:00
Johann150 54be3d4ad6
client: simplify page editor 2022-08-01 08:34:25 +02:00
Johann150 7ffcbfa923
adjust types & api for pages 2022-08-01 08:34:25 +02:00
Johann150 1e63345f1f
remove unused locale strings 2022-08-01 08:34:24 +02:00
Johann150 35a5354650
remove client code related to pages 2022-08-01 08:34:08 +02:00
77 changed files with 373 additions and 8535 deletions

View File

@ -1233,7 +1233,6 @@ _pages:
liked: "الصفحات المُعجب بها"
featured: "الأكثر شعبية"
contents: "المحتوى"
variables: "متغيّرات"
title: "العنوان"
url: "رابط الصفحة"
summary: "ملخص الصفحة"
@ -1244,238 +1243,6 @@ _pages:
fontSansSerif: "Sans Serif"
eyeCatchingImageSet: "عيّن صورة مصغّرة"
eyeCatchingImageRemove: "احذف صورة مصغّرة"
chooseBlock: "إضافة كتلة"
selectType: "اختر النوع"
enterVariableName: "أدخل اسم المتغيّر"
variableNameIsAlreadyUsed: "هذا الاسم محجوز"
contentBlocks: "المحتوى"
inputBlocks: "مُدخل"
specialBlocks: "خاص"
blocks:
text: "نص"
textarea: "حقل نصي"
section: "قسم"
image: "الصور"
button: "زرّ"
_if:
variable: "متغيّر"
post: "أنشئ ملاحظة"
_post:
text: "المحتوى"
textInput: "مُدخل نصي"
_textInput:
name: "اسم المتغير"
text: "العنوان"
default: "القيمة الافتراضية"
textareaInput: "مدخل نصي متعدد الأسطر"
_textareaInput:
name: "اسم المتغير"
text: "العنوان"
default: "القيمة الافتراضية"
numberInput: "مُدخل رقمي"
_numberInput:
name: "اسم المتغير"
text: "العنوان"
default: "القيمة الافتراضية"
_canvas:
width: "العُرض"
height: "الإرتفاع"
note: "ملاحظة مضمّنة"
_note:
id: "معرّف الملاحظة"
idDescription: "كبديل يمكنك إدخال رابك الملاحظة هنا"
detailed: "عرض مفصّل"
switch: "بدّل"
_switch:
name: "اسم المتغير"
text: "العنوان"
default: "القيمة الافتراضية"
counter: "العداد"
_counter:
name: "اسم المتغير"
text: "العنوان"
inc: "زِد"
_button:
text: "العنوان"
colored: "ملوّن"
action: "الإجراء عند ضغط الزّر"
_action:
dialog: "أظهر مربع حوار"
_dialog:
content: "المحتوى"
resetRandom: "صفِّر البذرة"
pushEvent: "أرسل حدثًا"
_pushEvent:
event: "اسم الحدث"
message: "إظهار رسالة عند التفعيل"
variable: "أرسل المتغيّر"
no-variable: "لا شيء"
_callAiScript:
functionName: "اسم الدالة"
radioButton: "الخيار "
_radioButton:
name: "اسم المتغير"
title: "العنوان"
values: "قائمة الخيارات (كل خيار في سطر لوحده)"
default: "القيمة الافتراضية"
script:
categories:
logical: "عمليّة منطقيّة"
operation: "حساب"
comparison: "مقارنة"
random: "عشوائي"
value: "القيم"
fn: "دوال"
text: "إجراءات على النصوص"
convert: "تحويل"
list: "القوائم"
blocks:
text: "نص"
textList: "قائمة نصية"
_textList:
info: "اجعل كل مدخل في سطر لوحده"
strLen: "طول النص"
_strLen:
arg1: "نص"
strPick: "استخرج محرفًا"
_strPick:
arg1: "نص"
arg2: "موضع المحرف"
strReplace: "استبدال النّص"
_strReplace:
arg1: "نص"
arg2: "استُبدِل بـ"
arg3: "استُبدِل بـ"
strReverse: "اقلب النص"
_strReverse:
arg1: "نص"
_join:
arg1: "القوائم"
arg2: "فاصل"
add: "إضافة"
_add:
arg1: "أ"
arg2: "ب"
subtract: "اطرح"
_subtract:
arg1: "أ"
arg2: "ب"
multiply: "اضرب"
_multiply:
arg1: "أ"
arg2: "ب"
divide: "اقسم"
_divide:
arg1: "أ"
arg2: "ب"
mod: "الباقي"
_mod:
arg1: "أ"
arg2: "ب"
round: "تقريب عدد عشري"
_round:
arg1: "رقم"
eq: "أ و ب متساويان"
_eq:
arg1: "أ"
arg2: "ب"
notEq: "أ و ب مختلفان"
_notEq:
arg1: "أ"
arg2: "ب"
and: "أ و ب"
_and:
arg1: "أ"
arg2: "ب"
or: "أ أو ب"
_or:
arg1: "أ"
arg2: "ب"
lt: "أ أصغر من ب"
_lt:
arg1: "أ"
arg2: "ب"
gt: "أ أكبر من ب"
_gt:
arg1: "أ"
arg2: "ب"
ltEq: "أ أصغر من أو يساوي ب"
_ltEq:
arg1: "أ"
arg2: "ب"
gtEq: "أ أكبر من أو يساوي ب"
_gtEq:
arg1: "أ"
arg2: "ب"
if: "فرع"
random: "عشوائي"
rannum: "رقم عشوائي"
_rannum:
arg1: "أدنى قيمة"
arg2: "أقصى قيمة"
randomPick: "اختر عشوائيًا من القائمة"
_randomPick:
arg1: "القوائم"
dailyRandom: "عشوائي (يتغير مرة يوميًا لكل مستخدم)"
dailyRannum: "رقم عشوائي (يتغير مرة يوميًا لكل مستخدم)"
_dailyRannum:
arg1: "أدنى قيمة"
arg2: "أقصى قيمة"
dailyRandomPick: "اختيار عشوائي من قائمة (يتغير مرة يوميًا لكل مستخدم)"
_dailyRandomPick:
arg1: "القوائم"
seedRandom: "عشوائي (عبر بذرة)"
_seedRandom:
arg1: "البذرة"
seedRannum: "رقم عشوائي (عبر بذرة)"
_seedRannum:
arg1: "البذرة"
arg2: "أدنى قيمة"
arg3: "أقصى قيمة"
seedRandomPick: "اختيار عشوائي من القائمة (عبر بذرة)"
_seedRandomPick:
arg1: "البذرة"
arg2: "القوائم"
DRPWPM: "اختيار عشوائي من قائمة الاحتمالات (تتغير مرة يوميًا لكل مستخدم)"
_DRPWPM:
arg1: "قائمة نصية"
pick: "اختر من القائمة"
_pick:
arg1: "القوائم"
arg2: "الموضع"
listLen: "طول القائمة"
_listLen:
arg1: "القوائم"
number: "رقم"
stringToNumber: "حوّل نصًا إلى رقم"
_stringToNumber:
arg1: "نص"
numberToString: "حوّل رقمًا إلى نص"
_numberToString:
arg1: "رقم"
_splitStrByLine:
arg1: "نص"
ref: "متغيّر"
aiScriptVar: "متغيّر AiScript"
fn: "دالة"
_fn:
slots: "خانات"
arg1: "المُخرج"
for: "حلقة تكرار"
_for:
arg1: "عدد مرات التكرار"
arg2: "الإجراء"
typeError: "الخانة {slot} تقبل \"{expect}\" لكن القيمة المعطاة هي \"{actual}\"!"
thereIsEmptySlot: "الخانة {slot} فارغة!"
types:
string: "نص"
number: "رقم"
array: "القوائم"
stringArray: "قائمة نصية"
emptySlot: "خانة فارغة"
enviromentVariables: "متغيرات البيئة"
pageVariables: "متغيرات الصفحة"
argVariables: "خانة إدخال"
_relayStatus:
requesting: "مُعلّق"
accepted: "مقبول"

View File

@ -1325,10 +1325,7 @@ _pages:
my: "আমার পৃষ্ঠাগুলি"
liked: "পছন্দ করা পৃষ্ঠাগুলি"
featured: "জনপ্রিয়"
inspector: "ইনিস্পেক্টর"
contents: "বিষয়বস্তু"
content: "পৃষ্ঠার ব্লক"
variables: "চলকগুলি"
title: "শিরোনাম"
url: "পৃষ্ঠার URL"
summary: "পৃষ্ঠার বর্ণনা"
@ -1339,262 +1336,6 @@ _pages:
fontSansSerif: "স্যান্স সেরিফ"
eyeCatchingImageSet: "থাম্বনেইল সেট করুন"
eyeCatchingImageRemove: "থাম্বনেইল সরান"
chooseBlock: "ব্লক যোগ করুন"
selectType: "ধরন নির্বাচন করুন"
enterVariableName: "চলকের নাম লিখুন"
variableNameIsAlreadyUsed: "চলকের নামটি ইতিপূর্বে ব্যাবহৃত হয়েছে"
contentBlocks: "বিষয়বস্তু"
inputBlocks: "ইনপুট"
specialBlocks: "বিশেষ"
blocks:
text: "লেখা"
textarea: "টেক্সট এরিয়া"
section: "বিভাগ"
image: "ছবি"
button: "বাটন"
if: "যদি"
_if:
variable: "চলকগুলি"
post: "নোট লিখুন"
_post:
text: "বিষয়বস্তু"
attachCanvasImage: "ক্যানভাস ছবিসহ পোস্ট করুন"
canvasId: "ক্যানভাস ID"
textInput: "টেক্সট ইনপুট"
_textInput:
name: "চলকের নাম"
text: "শিরোনাম"
default: "ডিফল্ট মান"
textareaInput: "একাধিক লাইনের টেক্সট ইনপুট"
_textareaInput:
name: "চলকের নাম"
text: "শিরোনাম"
default: "ডিফল্ট মান"
numberInput: "সংখ্যা ইনপুট"
_numberInput:
name: "চলকের নাম"
text: "শিরোনাম"
default: "ডিফল্ট মান"
canvas: "ক্যানভাস"
_canvas:
id: "ক্যানভাস ID"
width: "প্রস্থ"
height: "উচ্চতা"
note: "এম্বেড নোট"
_note:
id: "নোট ID"
idDescription: "আপনি এর বদলে নোটের URL পেস্ট করতে পারেন."
detailed: "বিস্তারিত দেখুন"
switch: "সুইচ"
_switch:
name: "চলকের নাম"
text: "শিরোনাম"
default: "ডিফল্ট মান"
counter: "কাউন্টার"
_counter:
name: "চলকের নাম"
text: "শিরোনাম"
inc: "এভাবে মান বাড়ান"
_button:
text: "শিরোনাম"
colored: "রঙ্গিন"
action: "বাটনে ক্লিক করলে যা হবে"
_action:
dialog: "ডায়ালগ দেখান "
_dialog:
content: "বিষয়বস্তু"
resetRandom: "র‍্যানডম সিড রিসেট করুন"
pushEvent: "ইভেন্ট পাঠান"
_pushEvent:
event: "ইভেন্টের নাম"
message: "চালু হলে প্রদর্শনের জন্য বার্তা"
variable: "পাঠানো চলক"
no-variable: "কিছুই না"
callAiScript: "AiScript চালান"
_callAiScript:
functionName: "ফাংশনের নাম"
radioButton: "বহুনির্বাচনী"
_radioButton:
name: "চলকের নাম"
title: "শিরোনাম"
values: "বিকল্পগুলিকে আলাদা লাইনে লিখুন"
default: "ডিফল্ট মান"
script:
categories:
flow: "নিয়ন্ত্রণ"
logical: "লজিক্যাল অপারেশন"
operation: "হিসাব-নিকাশ"
comparison: "তুলনা"
random: "র‍্যান্ডম"
value: "মান"
fn: "ফাংশন"
text: "টেক্সট ম্যানিপুলেশন"
convert: "রুপান্তর"
list: "লিস্ট"
blocks:
text: "লেখা"
multiLineText: "লেখা (একাধিক লাইন)"
textList: "লেখার লিস্ট"
_textList:
info: "প্রতিটি এন্ট্রিকে আলাদা লাইনে লিখুন"
strLen: "লেখার দৈর্ঘ্য"
_strLen:
arg1: "লেখা"
strPick: "অক্ষর বের করে আনুন"
_strPick:
arg1: "লেখা"
arg2: "অক্ষরের অবস্থান"
strReplace: "লেখা প্রতিস্থাপন"
_strReplace:
arg1: "লেখা"
arg2: "যে লেখা প্রতিস্থাপন করা হবে"
arg3: "যা দ্বারা প্রতিস্থাপন করা হবে"
strReverse: "লেখা উল্টান"
_strReverse:
arg1: "লেখা"
join: "লেখা যুক্ত করুন"
_join:
arg1: "লিস্ট"
arg2: "বিভাজক"
add: "যোগ"
_add:
arg1: "A"
arg2: "B"
subtract: "বিয়োগ"
_subtract:
arg1: "A"
arg2: "B"
multiply: "গুন"
_multiply:
arg1: "A"
arg2: "B"
divide: "ভাগ"
_divide:
arg1: "A"
arg2: "B"
mod: "ভাগশেষ"
_mod:
arg1: "A"
arg2: "B"
round: "দশমিক রাউন্ড করুন"
_round:
arg1: "সংখ্যা"
eq: "A ও B সমান"
_eq:
arg1: "A"
arg2: "B"
notEq: "A ও B সমান না"
_notEq:
arg1: "A"
arg2: "B"
and: "A এবং B"
_and:
arg1: "A"
arg2: "B"
or: "A অথবা B"
_or:
arg1: "A"
arg2: "B"
lt: "< A , B হতে কম"
_lt:
arg1: "A"
arg2: "B"
gt: "> A , B হতে বেশী"
_gt:
arg1: "A"
arg2: "B"
ltEq: "<= A , B হতে কম বা সমান"
_ltEq:
arg1: "A"
arg2: "B"
gtEq: ">= A , B হতে বেশী বা সমান"
_gtEq:
arg1: "A"
arg2: "B"
if: "যদি"
_if:
arg1: "যদি"
arg2: "তাহলে"
arg3: "তাছাড়া"
not: "না"
_not:
arg1: "না"
random: "র‍্যান্ডম"
_random:
arg1: "সম্ভাব্যতা"
rannum: "র‍্যানডম সংখ্যা"
_rannum:
arg1: "ন্যূনতম মান"
arg2: "সর্বোচ্চ মান"
randomPick: "তালিকা থেকে দৈবচয়ন করুন"
_randomPick:
arg1: "লিস্ট"
dailyRandom: "র‍্যান্ডম সংখ্যা (প্রতিটি ব্যবহারকারীর জন্য প্রতিদিন পরিবর্তীত হয়)"
_dailyRandom:
arg1: "সম্ভাব্যতা"
dailyRannum: "র‍্যান্ডম সংখ্যা (প্রতিটি ব্যবহারকারীর জন্য প্রতিদিন পরিবর্তীত হয়)"
_dailyRannum:
arg1: "ন্যূনতম মান"
arg2: "সর্বোচ্চ মান"
dailyRandomPick: "তালিকা থেকে এলোমেলোভাবে নির্বাচন করুন (প্রতিটি ব্যবহারকারীর জন্য প্রতিদিন পরিবর্তীত হয়)"
_dailyRandomPick:
arg1: "লিস্ট"
seedRandom: "র‍্যানডম (সীড দ্বারা)"
_seedRandom:
arg1: "সীড"
arg2: "সম্ভাব্যতা"
seedRannum: "র‍্যানডম সংখ্যা (সীড দ্বারা)"
_seedRannum:
arg1: "সীড"
arg2: "ন্যূনতম মান"
arg3: "সর্বোচ্চ মান"
seedRandomPick: "তালিকা থেকে দৈবচয়ন করুন (সীড দ্বারা)"
_seedRandomPick:
arg1: "সীড"
arg2: "লিস্ট"
DRPWPM: "সম্ভাব্যতা সহ একটি তালিকা থেকে এলোমেলোভাবে নির্বাচন করুন (প্রতিটি ব্যবহারকারীর জন্য প্রতিদিন)"
_DRPWPM:
arg1: "লেখার লিস্ট"
pick: "তালিকা থেকে নির্বাচন করুন"
_pick:
arg1: "লিস্ট"
arg2: "অবস্থান"
listLen: "লিস্টের দৈর্ঘ্য পান"
_listLen:
arg1: "লিস্ট"
number: "সংখ্যা"
stringToNumber: "পাঠ্য থেকে সংখ্যা"
_stringToNumber:
arg1: "লেখা"
numberToString: "সংখ্যা থেকে পাঠ্য"
_numberToString:
arg1: "সংখ্যা"
splitStrByLine: "পাঠ্যকে লাইনে বিভক্ত করুন"
_splitStrByLine:
arg1: "লেখা"
ref: "চলক"
aiScriptVar: "AiScript চলক"
fn: "ফাংশন"
_fn:
slots: "স্লটগুলি"
slots-info: "প্রতিটি স্লটকে আলাদা লাইনে লিখুন"
arg1: "আউটপুট"
for: "for-লুপ"
_for:
arg1: "কতবার চলবে"
arg2: "অ্যাকশন"
typeError: "স্লট {slot}, {expect} ধরনের মান গ্রহণ করে, কিন্তু {actual} ধরনের মান দেওয়া হয়েছে!"
thereIsEmptySlot: "স্লট {slot} খালি!"
types:
string: "লেখা"
number: "সংখ্যা"
boolean: "ফ্ল্যাগ"
array: "লিস্ট"
stringArray: "লেখার লিস্ট"
emptySlot: "খালি স্লট"
enviromentVariables: "এনভাইরনমেন্ট ভ্যারিয়েবল"
pageVariables: "পেজের চলক"
argVariables: "ইনপুটের জায়গা"
_relayStatus:
requesting: "অপেক্ষমান"
accepted: "অনুমোদিত"

View File

@ -147,25 +147,6 @@ _profile:
_exportOrImport:
followingList: "Seguint"
userLists: "Llistes"
_pages:
script:
categories:
list: "Llistes"
blocks:
_join:
arg1: "Llistes"
_randomPick:
arg1: "Llistes"
_dailyRandomPick:
arg1: "Llistes"
_seedRandomPick:
arg2: "Llistes"
_pick:
arg1: "Llistes"
_listLen:
arg1: "Llistes"
types:
array: "Llistes"
_notification:
youWereFollowed: "t'ha seguit"
_types:

View File

@ -513,27 +513,6 @@ _charts:
federation: "Federace"
_timelines:
home: "Domů"
_pages:
blocks:
image: "Obrázky"
script:
categories:
list: "Seznamy"
blocks:
_join:
arg1: "Seznamy"
_randomPick:
arg1: "Seznamy"
_dailyRandomPick:
arg1: "Seznamy"
_seedRandomPick:
arg2: "Seznamy"
_pick:
arg1: "Seznamy"
_listLen:
arg1: "Seznamy"
types:
array: "Seznamy"
_notification:
youWereFollowed: "Máte nového následovníka"
youWereInvitedToGroup: "Pozvat do skupiny"

View File

@ -1328,10 +1328,7 @@ _pages:
my: "Meine Seiten"
liked: "Seiten, die mir gefallen"
featured: "Beliebt"
inspector: "Inspektor"
contents: "Inhalte"
content: "Seitenblock"
variables: "Variablen"
title: "Titel"
url: "Seiten-URL"
summary: "Zusammenfassung"
@ -1342,262 +1339,6 @@ _pages:
fontSansSerif: "Sans Serif"
eyeCatchingImageSet: "Vorschaubild festlegen"
eyeCatchingImageRemove: "Vorschaubild entfernen"
chooseBlock: "Block hinzufügen"
selectType: "Typ auswählen"
enterVariableName: "Gib einen Variablennamen ein"
variableNameIsAlreadyUsed: "Dieser Name wird bereits von einer anderen Variable verwendet"
contentBlocks: "Inhalt"
inputBlocks: "Eingabe"
specialBlocks: "Spezial"
blocks:
text: "Text"
textarea: "Textfeld"
section: "Abschnitt"
image: "Bild"
button: "Knopf"
if: "Falls"
_if:
variable: "Variable"
post: "Notizfenster"
_post:
text: "Inhalt"
attachCanvasImage: "Leinwandbild anfügen"
canvasId: "Leinwand-ID"
textInput: "Texteingabe"
_textInput:
name: "Variablenname"
text: "Titel"
default: "Standardwert"
textareaInput: "Mehrzeiliges Texteingabefeld"
_textareaInput:
name: "Variablenname"
text: "Titel"
default: "Standardwert"
numberInput: "Zahleneingabe"
_numberInput:
name: "Variablenname"
text: "Titel"
default: "Standardwert"
canvas: "Leinwand"
_canvas:
id: "Leinwand-ID"
width: "Breite"
height: "Höhe"
note: "Eingebettete Notiz"
_note:
id: "Notiz-ID"
idDescription: "Du kannst alternativ auch die Notiz-URL angeben."
detailed: "Detailierte Ansicht"
switch: "Fallunterscheidung"
_switch:
name: "Variablenname"
text: "Titel"
default: "Standardwert"
counter: "Zähler"
_counter:
name: "Variablenname"
text: "Titel"
inc: "Schrittgröße"
_button:
text: "Titel"
colored: "Farbig"
action: "Aktion, die bei Knopfdruck ausgeführt wird"
_action:
dialog: "Dialogfenster anzeigen"
_dialog:
content: "Inhalt"
resetRandom: "Zufallswert zurücksetzen"
pushEvent: "Ein Event senden"
_pushEvent:
event: "Eventname"
message: "Nachricht, die bei Auslösung des Events angezeigt werden soll"
variable: "Variable, die gesendet werden soll"
no-variable: "Keine"
callAiScript: "AiScript ausführen"
_callAiScript:
functionName: "Funktionsname"
radioButton: "Optionsfeld"
_radioButton:
name: "Variablenname"
title: "Titel"
values: "Durch Zeilenümbrüche getrennte Auswahlmöglichkeiten"
default: "Standardwert"
script:
categories:
flow: "Steuerung"
logical: "Logische Operationen"
operation: "Berechnungen"
comparison: "Vergleiche"
random: "Zufällig"
value: "Werte"
fn: "Funktionen"
text: "Textoperationen"
convert: "Konvertierungen"
list: "Listen"
blocks:
text: "Text"
multiLineText: "Text (Mehrzeilig)"
textList: "Textliste"
_textList:
info: "Trenne jeden Eintrag mit einem Zeilenumbruch"
strLen: "Textlänge"
_strLen:
arg1: "Text"
strPick: "Text extrahieren"
_strPick:
arg1: "Text"
arg2: "Textposition"
strReplace: "Textersetzung"
_strReplace:
arg1: "Text"
arg2: "Zu ersetzender Text"
arg3: "Ersetzen mit"
strReverse: "Text umkehren"
_strReverse:
arg1: "Text"
join: "Text zusammenfügen"
_join:
arg1: "Liste"
arg2: "Trennzeichen"
add: "Addieren"
_add:
arg1: "A"
arg2: "B"
subtract: "Subtrahieren"
_subtract:
arg1: "A"
arg2: "B"
multiply: "Multiplizieren"
_multiply:
arg1: "A"
arg2: "B"
divide: "Teilen"
_divide:
arg1: "A"
arg2: "B"
mod: "Rest"
_mod:
arg1: "A"
arg2: "B"
round: "Rundung von Dezimalstellen"
_round:
arg1: "Nummer"
eq: "A und B sind gleich"
_eq:
arg1: "A"
arg2: "B"
notEq: "A und B sind nicht gleich"
_notEq:
arg1: "A"
arg2: "B"
and: "A UND B"
_and:
arg1: "A"
arg2: "B"
or: "A ODER B"
_or:
arg1: "A"
arg2: "B"
lt: "< A ist kleiner als B"
_lt:
arg1: "A"
arg2: "B"
gt: "> A ist größer als B"
_gt:
arg1: "A"
arg2: "B"
ltEq: "<= A ist kleiner als oder gleich B"
_ltEq:
arg1: "A"
arg2: "B"
gtEq: ">= A ist größer als oder gleich B"
_gtEq:
arg1: "A"
arg2: "B"
if: "Kondition"
_if:
arg1: "Falls"
arg2: "Wenn wahr"
arg3: "Sonst"
not: "NICHT"
_not:
arg1: "NICHT"
random: "Zufällig"
_random:
arg1: "Warscheinlichkeit"
rannum: "Zufallsnummer"
_rannum:
arg1: "Minimum"
arg2: "Maximum"
randomPick: "Zufallswahl aus Liste"
_randomPick:
arg1: "Liste"
dailyRandom: "Zufällig (Pro Nutzer jeden Tag verschieden)"
_dailyRandom:
arg1: "Warscheinlichkeit"
dailyRannum: "Zufallsnummer (Pro Nutzer jeden Tag verschieden)"
_dailyRannum:
arg1: "Minimum"
arg2: "Maximum"
dailyRandomPick: "Zufallsauswahl aus einer Liste (Pro Nutzer jeden Tag verschieden)"
_dailyRandomPick:
arg1: "Liste"
seedRandom: "Zufällig (mit Startwert / Seed)"
_seedRandom:
arg1: "Startwert / Seed"
arg2: "Warscheinlichkeit"
seedRannum: "Zufallsnummer (mit Startwert / Seed)"
_seedRannum:
arg1: "Startwert / Seed"
arg2: "Minimum"
arg3: "Maximum"
seedRandomPick: "Zufallsauswahl aus Liste (mit Startwert / Seed)"
_seedRandomPick:
arg1: "Startwert / Seed"
arg2: "Liste"
DRPWPM: "Zufallsauswahl aus gewichteter Liste (Pro Nutzer jeden Tag verschieden)"
_DRPWPM:
arg1: "Textliste"
pick: "Aus einer Liste wählen"
_pick:
arg1: "Liste"
arg2: "Position"
listLen: "Listenlänge abrufen"
_listLen:
arg1: "Liste"
number: "Nummer"
stringToNumber: "Text zu Nummer"
_stringToNumber:
arg1: "Text"
numberToString: "Nummer zu Text"
_numberToString:
arg1: "Nummer"
splitStrByLine: "Text nach Zeilenumbrüchen aufteilen"
_splitStrByLine:
arg1: "Text"
ref: "Variable"
aiScriptVar: "AiScript Variable"
fn: "Funktion"
_fn:
slots: "Slots"
slots-info: "Trenne jeden Slot mit einem Zeilenumbruch"
arg1: "Ausgabe"
for: "for-Schleife"
_for:
arg1: "Anzahl der Schleifendurchläufe"
arg2: "Aktion"
typeError: "Slot {slot} akzeptiert Werte vom Typ „{expect}“, aber es wurde ein „{actual}“ Wert angegeben!"
thereIsEmptySlot: "Slot {slot} ist leer!"
types:
string: "Text"
number: "Nummer"
boolean: "Wahrheitswert"
array: "Liste"
stringArray: "Textliste"
emptySlot: "Leerer Slot"
enviromentVariables: "Umgebungsvariable"
pageVariables: "Seitenelemente"
argVariables: "Eingabeslots"
_relayStatus:
requesting: "Ausstehend"
accepted: "Akzeptiert"

View File

@ -1343,10 +1343,7 @@ _pages:
my: "My Pages"
liked: "Liked Pages"
featured: "Popular"
inspector: "Inspector"
contents: "Contents"
content: "Page block"
variables: "Variables"
title: "Title"
url: "Page URL"
summary: "Page summary"
@ -1357,262 +1354,6 @@ _pages:
fontSansSerif: "Sans Serif"
eyeCatchingImageSet: "Set thumbnail"
eyeCatchingImageRemove: "Delete thumbnail"
chooseBlock: "Add a block"
selectType: "Select a type"
enterVariableName: "Enter a variable name"
variableNameIsAlreadyUsed: "This variable name is already in use"
contentBlocks: "Content"
inputBlocks: "Input"
specialBlocks: "Special"
blocks:
text: "Text"
textarea: "Text area"
section: "Section"
image: "Images"
button: "Button"
if: "If"
_if:
variable: "Variable"
post: "Posting form"
_post:
text: "Content"
attachCanvasImage: "Attach canvas image"
canvasId: "Canvas ID"
textInput: "Text input"
_textInput:
name: "Variable name"
text: "Title"
default: "Default value"
textareaInput: "Multiline text input"
_textareaInput:
name: "Variable name"
text: "Title"
default: "Default value"
numberInput: "Numeric input"
_numberInput:
name: "Variable name"
text: "Title"
default: "Default value"
canvas: "Canvas"
_canvas:
id: "Canvas ID"
width: "Width"
height: "Height"
note: "Embedded note"
_note:
id: "Note ID"
idDescription: "You can alternatively paste the note URL here."
detailed: "Detailed view"
switch: "Switch"
_switch:
name: "Variable name"
text: "Title"
default: "Default value"
counter: "Counter"
_counter:
name: "Variable name"
text: "Title"
inc: "Step"
_button:
text: "Title"
colored: "Colored"
action: "Behavior when the button is pressed"
_action:
dialog: "Show a dialog"
_dialog:
content: "Content"
resetRandom: "Reset the random seed"
pushEvent: "Send an event"
_pushEvent:
event: "Event name"
message: "Message to display when activated"
variable: "Variable to send"
no-variable: "None"
callAiScript: "Invoke AiScript"
_callAiScript:
functionName: "Function name"
radioButton: "Choice"
_radioButton:
name: "Variable name"
title: "Title"
values: "List of choices separated by line breaks"
default: "Default value"
script:
categories:
flow: "Flow control"
logical: "Logical operation"
operation: "Computation"
comparison: "Comparison"
random: "Random"
value: "Values"
fn: "Functions"
text: "Text operations"
convert: "Transformations"
list: "Lists"
blocks:
text: "Text"
multiLineText: "Text (multiline)"
textList: "Text list"
_textList:
info: "Separate each entry with a line break"
strLen: "Text length"
_strLen:
arg1: "Text"
strPick: "Extract string"
_strPick:
arg1: "Text"
arg2: "String location"
strReplace: "Replacement string"
_strReplace:
arg1: "Text"
arg2: "Text to be replaced"
arg3: "Replace with"
strReverse: "Flip text"
_strReverse:
arg1: "Text"
join: "Text concatenation"
_join:
arg1: "Lists"
arg2: "Separator"
add: "Add"
_add:
arg1: "A"
arg2: "B"
subtract: "Subtract"
_subtract:
arg1: "A"
arg2: "B"
multiply: "Multiply"
_multiply:
arg1: "A"
arg2: "B"
divide: "Divide"
_divide:
arg1: "A"
arg2: "B"
mod: "Remainder"
_mod:
arg1: "A"
arg2: "B"
round: "Decimal rounding"
_round:
arg1: "Number"
eq: "A and B are equal"
_eq:
arg1: "A"
arg2: "B"
notEq: "A and B are different"
_notEq:
arg1: "A"
arg2: "B"
and: "A AND B"
_and:
arg1: "A"
arg2: "B"
or: "A OR B"
_or:
arg1: "A"
arg2: "B"
lt: "< A is less than B"
_lt:
arg1: "A"
arg2: "B"
gt: "> A is larger than B"
_gt:
arg1: "A"
arg2: "B"
ltEq: "<= A is less than or equal to B"
_ltEq:
arg1: "A"
arg2: "B"
gtEq: ">= A is greater than or equal to B"
_gtEq:
arg1: "A"
arg2: "B"
if: "Branch"
_if:
arg1: "If"
arg2: "Then"
arg3: "Else"
not: "NOT"
_not:
arg1: "NOT"
random: "Random"
_random:
arg1: "Probability"
rannum: "Random number"
_rannum:
arg1: "Minimum value"
arg2: "Maximum value"
randomPick: "Randomly choose from list"
_randomPick:
arg1: "List"
dailyRandom: "Random (Changes once a day for each user)"
_dailyRandom:
arg1: "Probability"
dailyRannum: "Random number (Changes once a day for each user)"
_dailyRannum:
arg1: "Minimum value"
arg2: "Maximum value"
dailyRandomPick: "Randomly choose from a list (Changes once a day for each user)"
_dailyRandomPick:
arg1: "List"
seedRandom: "Random (with seed)"
_seedRandom:
arg1: "Seed"
arg2: "Probability"
seedRannum: "Random number (with seed)"
_seedRannum:
arg1: "Seed"
arg2: "Minimum value"
arg3: "Maximum value"
seedRandomPick: "Randomly choose from list (with seed)"
_seedRandomPick:
arg1: "Seed"
arg2: "List"
DRPWPM: "Randomly choose from weighted list (Changes once a day for each user)"
_DRPWPM:
arg1: "Text list"
pick: "Select from list"
_pick:
arg1: "List"
arg2: "Position"
listLen: "Get length of list"
_listLen:
arg1: "List"
number: "Number"
stringToNumber: "Text to number"
_stringToNumber:
arg1: "Text"
numberToString: "Number to text"
_numberToString:
arg1: "Number"
splitStrByLine: "Split text by line breaks"
_splitStrByLine:
arg1: "Text"
ref: "Variable"
aiScriptVar: "AiScript Variable"
fn: "Function"
_fn:
slots: "Slots"
slots-info: "Separate each slot with a line break"
arg1: "Output"
for: "for-Loop"
_for:
arg1: "Number of times to repeat"
arg2: "Action"
typeError: "Slot {slot} accepts values of type \"{expect}\", but the provided value is of type \"{actual}\"!"
thereIsEmptySlot: "Slot {slot} is empty!"
types:
string: "Text"
number: "Number"
boolean: "Flag"
array: "List"
stringArray: "Text list"
emptySlot: "Empty slot"
enviromentVariables: "Environment variables"
pageVariables: "Page variables"
argVariables: "Input slots"
_relayStatus:
requesting: "Pending"
accepted: "Accepted"

View File

@ -1208,10 +1208,7 @@ _pages:
unlike: "Quitar me gusta"
my: "Mis páginas"
liked: "Páginas que me gustan"
inspector: "Inspector"
contents: "Contenido"
content: "Bloque de página"
variables: "Variables"
title: "Título"
url: "URL de la página"
summary: "Resumen de la página"
@ -1222,257 +1219,6 @@ _pages:
fontSansSerif: "Sans Serif"
eyeCatchingImageSet: "Elegir imagen llamativa"
eyeCatchingImageRemove: "Borrar imagen llamativa"
chooseBlock: "Agregar bloque"
selectType: "Elegir tipo"
enterVariableName: "Ingrese el nombre de la variable"
variableNameIsAlreadyUsed: "El nombre de la variable ya está en uso"
contentBlocks: "Contenido"
inputBlocks: "Entrada"
specialBlocks: "Especial"
blocks:
text: "Texto"
textarea: "Área de texto"
section: "Sección"
image: "Imagen"
button: "Botón"
if: "si"
_if:
variable: "Variable"
post: "Formulario"
_post:
text: "Contenido"
attachCanvasImage: "Nota con lienzo como imagen"
canvasId: "Lienzo ID"
textInput: "Entrada de texto"
_textInput:
name: "Nombre de variable"
text: "Título"
default: "Valor predeterminado"
textareaInput: "Entrada de texto en múltiples lineas"
_textareaInput:
name: "Nombre de variable"
text: "Título"
default: "Valor predeterminado"
numberInput: "Entrada numérica"
_numberInput:
name: "Nombre de variable"
text: "Título"
default: "Valor predeterminado"
canvas: "Lienzo"
_canvas:
id: "Lienzo ID"
width: "Ancho"
height: "Altura"
switch: "Interruptor"
_switch:
name: "Nombre de variable"
text: "Título"
default: "Valor predeterminado"
counter: "Contador"
_counter:
name: "Nombre de variable"
text: "Título"
inc: "Aumentar cantidad"
_button:
text: "Título"
colored: "Color"
action: "Acción al presionar el botón"
_action:
dialog: "Mostrar cuadro de diálogo"
_dialog:
content: "Contenido"
resetRandom: "Resetear número aleatorio"
pushEvent: "Enviar evento"
_pushEvent:
event: "Nombre del evento"
message: "Mensaje mostrado al apretar"
variable: "Variable a enviar"
no-variable: "Ninguna"
callAiScript: "Invocar AiScript"
_callAiScript:
functionName: "Nombre de la función"
radioButton: "Botón de opción"
_radioButton:
name: "Nombre de variable"
title: "Título"
values: "Opciones separadas por una nueva linea"
default: "Valor predeterminado"
script:
categories:
flow: "Control de flujo"
logical: "Operación lógica"
operation: "Cálculo"
comparison: "Comparar"
random: "Aleatorio"
value: "Valores"
fn: "funciones"
text: "Manejo de texto"
convert: "Conversion"
list: "Listas"
blocks:
text: "Texto"
multiLineText: "Texto (multilinea)"
textList: "Lista de texto"
_textList:
info: "Separe cada texto con una linea nueva"
strLen: "Largo del texto"
_strLen:
arg1: "Texto"
strPick: "Extraer caracteres"
_strPick:
arg1: "Texto"
arg2: "Posición del caracter"
strReplace: "Sustituir texto"
_strReplace:
arg1: "Texto"
arg2: "Texto a reemplazar"
arg3: "Texto reemplazado"
strReverse: "Invertir texto"
_strReverse:
arg1: "Texto"
join: "Concatenar texto"
_join:
arg1: "Listas"
arg2: "Separador"
add: "Suma"
_add:
arg1: "A"
arg2: "B"
subtract: "Resta"
_subtract:
arg1: "A"
arg2: "B"
multiply: "Multiplicación"
_multiply:
arg1: "A"
arg2: "B"
divide: "División"
_divide:
arg1: "A"
arg2: "B"
mod: "Resto"
_mod:
arg1: "A"
arg2: "B"
round: "Redondear decimales"
_round:
arg1: "Número"
eq: "A y B son iguales"
_eq:
arg1: "A"
arg2: "B"
notEq: "A y B son distintos"
_notEq:
arg1: "A"
arg2: "B"
and: "A y B"
_and:
arg1: "A"
arg2: "B"
or: "A o B"
_or:
arg1: "A"
arg2: "B"
lt: "< A es menor que B"
_lt:
arg1: "A"
arg2: "B"
gt: "> A es mayor que B"
_gt:
arg1: "A"
arg2: "B"
ltEq: "<= A es menor o igual que B"
_ltEq:
arg1: "A"
arg2: "B"
gtEq: ">= A es mayor o igual que B"
_gtEq:
arg1: "A"
arg2: "B"
if: "Si"
_if:
arg1: "si"
arg2: "Entonces"
arg3: "Si no"
not: "Negación"
_not:
arg1: "Negación"
random: "Aleatorio"
_random:
arg1: "probabilidad"
rannum: "Número aleatorio"
_rannum:
arg1: "Mínimo"
arg2: "Máximo"
randomPick: "Elegir aleatoriamente de la lista"
_randomPick:
arg1: "Listas"
dailyRandom: "Aleatorio (Diariamente para cada usuario)"
_dailyRandom:
arg1: "probabilidad"
dailyRannum: "Número aleatorio (Diariamente para cada usuario)"
_dailyRannum:
arg1: "Mínimo"
arg2: "Máximo"
dailyRandomPick: "Elegir aleatoriamente de la lista (Diariamente para cada usuario)"
_dailyRandomPick:
arg1: "Listas"
seedRandom: "Aleatorio (semilla)"
_seedRandom:
arg1: "Semilla"
arg2: "probabilidad"
seedRannum: "Número aleatorio (semilla)"
_seedRannum:
arg1: "Semilla"
arg2: "Mínimo"
arg3: "Máximo"
seedRandomPick: "Elegir aleatoriamente de la lista (semilla)"
_seedRandomPick:
arg1: "Semilla"
arg2: "Listas"
DRPWPM: "Elegir aleatoriamente de la lista ponderada (Diariamente para cada usuario)"
_DRPWPM:
arg1: "Lista de texto"
pick: "Elegir de la lista"
_pick:
arg1: "Listas"
arg2: "Posición"
listLen: "Obtener largo de la lista"
_listLen:
arg1: "Listas"
number: "Número"
stringToNumber: "De texto a número"
_stringToNumber:
arg1: "Texto"
numberToString: "De número a texto"
_numberToString:
arg1: "Número"
splitStrByLine: "Separar texto en lineas"
_splitStrByLine:
arg1: "Texto"
ref: "Variables"
aiScriptVar: "Variable de AiScript"
fn: "funciones"
_fn:
slots: "Slots"
slots-info: "Separe cada uno de los slots con una linea nueva"
arg1: "Salida"
for: "Repetir"
_for:
arg1: "Cantidad de repeticiones"
arg2: "Acción"
typeError: "El slot {slot} acepta el tipo {expect} pero fue ingresado el tipo {actual}"
thereIsEmptySlot: "El slot {slot} está vacío"
types:
string: "Texto"
number: "Número"
boolean: "Booleano"
array: "Listas"
stringArray: "Lista de texto"
emptySlot: "Slot vacío"
enviromentVariables: "Variables de entorno"
pageVariables: "Items de la página"
argVariables: "Slot de entrada"
_relayStatus:
requesting: "Pendiente"
accepted: "Aceptar"

View File

@ -1311,10 +1311,7 @@ _pages:
my: "Mes pages"
liked: "Pages favorites"
featured: "Populaire"
inspector: "Inspecteur"
contents: "Contenu"
content: "Bloc de page"
variables: "Variables"
title: "Titre"
url: "URL de la page"
summary: "Résumé de page"
@ -1325,262 +1322,6 @@ _pages:
fontSansSerif: "Sans Serif"
eyeCatchingImageSet: "Définir une image attractive"
eyeCatchingImageRemove: "Supprimer l'image attractive"
chooseBlock: "Ajouter un bloc"
selectType: "Choisir un type"
enterVariableName: "Veuillez entrer un nom pour votre variable"
variableNameIsAlreadyUsed: "Ce nom de variable est déjà utilisé"
contentBlocks: "Contenu"
inputBlocks: "Blocs d'entrée"
specialBlocks: "Spécial"
blocks:
text: "Texte"
textarea: "Zone de texte"
section: "Section"
image: "Images"
button: "Bouton"
if: "Si"
_if:
variable: "Variables"
post: "Formulaire de publication"
_post:
text: "Contenu"
attachCanvasImage: "Publier avec Toile comme image"
canvasId: "Toile ID"
textInput: "Entrée textuelle"
_textInput:
name: "Nom de la variable"
text: "Titre"
default: "Valeur par défaut"
textareaInput: "Entrée textuelle multi-ligne"
_textareaInput:
name: "Nom de la variable"
text: "Titre"
default: "Valeur par défaut"
numberInput: "Entrée numérique"
_numberInput:
name: "Nom de la variable"
text: "Titre"
default: "Valeur par défaut"
canvas: "Toile"
_canvas:
id: "Toile ID"
width: "Largeur"
height: "Hauteur"
note: "Note intégrée"
_note:
id: "Identifiant de la note"
idDescription: "Pour configurer la note, vous pouvez aussi coller ici l'URL correspondante."
detailed: "Afficher les détails"
switch: "Interrupteur"
_switch:
name: "Nom de la variable"
text: "Titre"
default: "Valeur par défaut"
counter: "Compteur"
_counter:
name: "Nom de la variable"
text: "Titre"
inc: "Augmenter de"
_button:
text: "Titre"
colored: "Coloré"
action: "Opération à effectuer lorsque le bouton est pressé"
_action:
dialog: "Afficher une fenêtre de dialogue"
_dialog:
content: "Contenu"
resetRandom: "Réinitialiser un nombre aléatoire"
pushEvent: "Envoyer un évènement"
_pushEvent:
event: "Nom de lévènement"
message: "Message à afficher lorsquil est activé"
variable: "Variable à envoyer"
no-variable: "Rien"
callAiScript: "Appeler AiScript"
_callAiScript:
functionName: "Nom de la fonction"
radioButton: "Choix"
_radioButton:
name: "Nom de la variable"
title: "Titre"
values: "Liste des choix (un par ligne)"
default: "Valeur par défaut"
script:
categories:
flow: "Contrôle"
logical: "Opération logique"
operation: "Calculer"
comparison: "Comparer"
random: "Aléatoire"
value: "Valeur"
fn: "Fonction"
text: "Manipulation de texte"
convert: "Convertir"
list: "Listes"
blocks:
text: "Texte"
multiLineText: "Texte (multi-ligne)"
textList: "Liste de texte"
_textList:
info: "Veuillez séparer chaque entrée avec un saut de ligne"
strLen: "Longueur du texte"
_strLen:
arg1: "Texte"
strPick: "Extraire un caractère"
_strPick:
arg1: "Texte"
arg2: "Position du joueur"
strReplace: "Remplacement de texte"
_strReplace:
arg1: "Texte"
arg2: "Avant le remplacement"
arg3: "Après le remplacement"
strReverse: "Inverser le texte"
_strReverse:
arg1: "Texte"
join: "Concaténer du texte"
_join:
arg1: "Listes"
arg2: "Séparateur"
add: "Ajouter"
_add:
arg1: "A"
arg2: "B"
subtract: "Soustraire"
_subtract:
arg1: "A"
arg2: "B"
multiply: "Multiplier par"
_multiply:
arg1: "A"
arg2: "B"
divide: "Diviser par"
_divide:
arg1: "A"
arg2: "B"
mod: "Reste"
_mod:
arg1: "A"
arg2: "B"
round: "Arrondir les décimales"
_round:
arg1: "Numérique"
eq: "A et B sont égaux"
_eq:
arg1: "A"
arg2: "B"
notEq: "A et B sont différents"
_notEq:
arg1: "A"
arg2: "B"
and: "A et B"
_and:
arg1: "A"
arg2: "B"
or: "A ou B"
_or:
arg1: "A"
arg2: "B"
lt: "A est inférieur à B"
_lt:
arg1: "A"
arg2: "B"
gt: "A est supérieur à B"
_gt:
arg1: "A"
arg2: "B"
ltEq: "A est inférieur ou égal à B"
_ltEq:
arg1: "A"
arg2: "B"
gtEq: "A est supérieur ou égal à B"
_gtEq:
arg1: "A"
arg2: "B"
if: "Branche"
_if:
arg1: "Si"
arg2: "Si"
arg3: "Sinon"
not: "Nier"
_not:
arg1: "Nier"
random: "Aléatoire"
_random:
arg1: "Probabilité"
rannum: "Nombre aléatoire"
_rannum:
arg1: "Minimum"
arg2: "Maximum"
randomPick: "Sélectionner au hasard dans la liste"
_randomPick:
arg1: "Listes"
dailyRandom: "Aléatoire (Quotidien pour chaque utilisateur)"
_dailyRandom:
arg1: "Probabilité"
dailyRannum: "Numéros aléatoires (Quotidien pour chaque utilisateur)"
_dailyRannum:
arg1: "Minimum"
arg2: "Maximum"
dailyRandomPick: "Sélectionné au hasard dans la liste (Quotidien pour chaque utilisateur)"
_dailyRandomPick:
arg1: "Listes"
seedRandom: "Aléatoire (graine)"
_seedRandom:
arg1: "Graine"
arg2: "Probabilité"
seedRannum: "Nombre aléatoire (Graine)"
_seedRannum:
arg1: "Graine"
arg2: "Minimum"
arg3: "Maximum"
seedRandomPick: "Sélectionné au hasard dans la liste (graine)"
_seedRandomPick:
arg1: "Graine"
arg2: "Listes"
DRPWPM: "Sélectionné au hasard dans une liste de probabilités (Quotidien pour chaque utilisateur)"
_DRPWPM:
arg1: "Liste de texte"
pick: "Sélectionner dans la liste"
_pick:
arg1: "Listes"
arg2: "Position"
listLen: "Longueur de la liste"
_listLen:
arg1: "Listes"
number: "Numérique"
stringToNumber: "Convertir du texte en numérique"
_stringToNumber:
arg1: "Texte"
numberToString: "Convertir du numérique en texte"
_numberToString:
arg1: "Numérique"
splitStrByLine: "Séparer le texte par des sauts de lignes"
_splitStrByLine:
arg1: "Texte"
ref: "Variables"
aiScriptVar: "Variable d'AiScript"
fn: "Fonction"
_fn:
slots: "Slots"
slots-info: "Veuillez insérer un seul slot par ligne"
arg1: "Sortie"
for: "Répéter"
_for:
arg1: "Compter"
arg2: "Action"
typeError: "Le slot {slot} accepte \"{expect}\" mais a \"{actual}\" !"
thereIsEmptySlot: "Slot {slot} est vide !"
types:
string: "Texte"
number: "Numérique"
boolean: "Marqueur"
array: "Listes"
stringArray: "Liste de texte"
emptySlot: "Slot vide"
enviromentVariables: "Variables d'environnement"
pageVariables: "Élément de page"
argVariables: "Entrée slot"
_relayStatus:
requesting: "En attente"
accepted: "Accepté"

View File

@ -1327,10 +1327,7 @@ _pages:
my: "Halaman saya"
liked: "Halaman yang disukai"
featured: "Populer"
inspector: "Inspektor"
contents: "Konten"
content: "Blokir Halaman"
variables: "Variabel"
title: "Judul"
url: "URL Halaman"
summary: "Ringkasan Halaman"
@ -1341,262 +1338,6 @@ _pages:
fontSansSerif: "Sans-serif"
eyeCatchingImageSet: "Setel gambar yang menarik"
eyeCatchingImageRemove: "Hapus gambar yang menarik"
chooseBlock: "Tambahkan blokir"
selectType: "Pilih jenis"
enterVariableName: "Mohon masukkan nama untuk variabel kamu"
variableNameIsAlreadyUsed: "Nama ini sudah digunakan oleh variabel lain"
contentBlocks: "Konten"
inputBlocks: "Masukan"
specialBlocks: "Khusus"
blocks:
text: "Teks"
textarea: "Area teks"
section: "Bagian"
image: "Gambar"
button: "Tombol"
if: "Jika"
_if:
variable: "Variabel"
post: "Buat catatan"
_post:
text: "Isi"
attachCanvasImage: "Posting dengan kanvas sebagai gambar"
canvasId: "ID Kanvas"
textInput: "Masukan teks"
_textInput:
name: "Nama variabel"
text: "Judul"
default: "Nilai bawaan"
textareaInput: "Masukan teks multibaris"
_textareaInput:
name: "Nama variabel"
text: "Judul"
default: "Nilai bawaan"
numberInput: "Masukan angka"
_numberInput:
name: "Nama variabel"
text: "Judul"
default: "Nilai bawaan"
canvas: "Kanvas"
_canvas:
id: "ID Kanvas"
width: "Lebar"
height: "Tinggi"
note: "Catatan yang ditanam"
_note:
id: "ID Catatan"
idDescription: "Kamu dapat menyetel ini dengan menempelkan tautan URL Catatan."
detailed: "Tampilan rincian"
switch: "Beralih"
_switch:
name: "Nama variabel"
text: "Judul"
default: "Nilai bawaan"
counter: "Penghitung"
_counter:
name: "Nama variabel"
text: "Judul"
inc: "Meningkat dengan"
_button:
text: "Judul"
colored: "Diwarnai"
action: "Operasi akan dimulai ketika tombol ditekan"
_action:
dialog: "Tampilkan dialog"
_dialog:
content: "Isi"
resetRandom: "Atur ulang benih acak"
pushEvent: "Kirim event"
_pushEvent:
event: "Nama event"
message: "Pesan yang tampil ketika diaktifkan"
variable: "Variable untuk kirim"
no-variable: "Tidak ada"
callAiScript: "Panggil AiScript"
_callAiScript:
functionName: "Nama fungsi"
radioButton: "Pilihan"
_radioButton:
name: "Nama variabel"
title: "Judul"
values: "Daftar pilihan (dipisahkan dengan garis baru)"
default: "Nilai bawaan"
script:
categories:
flow: "Arus kendali"
logical: "Operasi logis"
operation: "Menghitung"
comparison: "Membandingkan"
random: "Acak"
value: "Nilai"
fn: "Fungsi"
text: "Operasi teks"
convert: "Mengubah"
list: "Daftar"
blocks:
text: "Teks"
multiLineText: "Teks (multibaris)"
textList: "Daftar teks"
_textList:
info: "Pisahkan setiap entri dengan baris baru"
strLen: "Panjang teks"
_strLen:
arg1: "Teks"
strPick: "Ekstrak karakter"
_strPick:
arg1: "Teks"
arg2: "Lokasi karakter"
strReplace: "Penggantian teks"
_strReplace:
arg1: "Teks"
arg2: "Teks yang akan diganti"
arg3: "Diganti dengan"
strReverse: "Balikkan teks"
_strReverse:
arg1: "Teks"
join: "Rangkaian teks"
_join:
arg1: "Daftar"
arg2: "Pemisah"
add: "Tambah"
_add:
arg1: "A"
arg2: "B"
subtract: "Kurangi"
_subtract:
arg1: "A"
arg2: "B"
multiply: "Kali"
_multiply:
arg1: "A"
arg2: "B"
divide: "Bagi"
_divide:
arg1: "A"
arg2: "B"
mod: "Sisa"
_mod:
arg1: "A"
arg2: "B"
round: "Bulat desimal"
_round:
arg1: "Angka"
eq: "A dan B adalah sama"
_eq:
arg1: "A"
arg2: "B"
notEq: "A dan B adalah berbeda"
_notEq:
arg1: "A"
arg2: "B"
and: "A DAN B"
_and:
arg1: "A"
arg2: "B"
or: "A ATAU B"
_or:
arg1: "A"
arg2: "B"
lt: "< A ikurang dari B"
_lt:
arg1: "A"
arg2: "B"
gt: "> A lebih dari B"
_gt:
arg1: "A"
arg2: "B"
ltEq: "<= A kurang dari sama dengan B"
_ltEq:
arg1: "A"
arg2: "B"
gtEq: ">= A lebih dari sama dengan B"
_gtEq:
arg1: "A"
arg2: "B"
if: "Cabang"
_if:
arg1: "Jika"
arg2: "Jika benar"
arg3: "Jika salah"
not: "BUKAN"
_not:
arg1: "NOT"
random: "Acak"
_random:
arg1: "Probabilitas"
rannum: "Angka acak"
_rannum:
arg1: "Nilai minimum"
arg2: "Nilai maksimum"
randomPick: "Pilih secara acak dari daftar"
_randomPick:
arg1: "Daftar"
dailyRandom: "Acak (bertahan sehari)"
_dailyRandom:
arg1: "Probabilitas"
dailyRannum: "Angka acak (bertahan sehari)"
_dailyRannum:
arg1: "Nilai minimum"
arg2: "Nilai maksimum"
dailyRandomPick: "Pilih secara acak dari daftar (bertahan sehari)"
_dailyRandomPick:
arg1: "Daftar"
seedRandom: "Acak (dengan seed)"
_seedRandom:
arg1: "Seed"
arg2: "Probabilitas"
seedRannum: "Angka acak (dengan seed)"
_seedRannum:
arg1: "Seed"
arg2: "Nilai minimum"
arg3: "Nilai maksimum"
seedRandomPick: "Pilih secara acak dari daftar (dengan seed)"
_seedRandomPick:
arg1: "Seed"
arg2: "Daftar"
DRPWPM: "Pilih secara acak dari daftar berbobot (bertahan sehari)"
_DRPWPM:
arg1: "Daftar teks"
pick: "Pilih dari daftar"
_pick:
arg1: "Daftar"
arg2: "Posisi"
listLen: "Dapatkan panjangnya dari daftar"
_listLen:
arg1: "Daftar"
number: "Angka"
stringToNumber: "Teks ke angka"
_stringToNumber:
arg1: "Teks"
numberToString: "Angka ke teks"
_numberToString:
arg1: "Angka"
splitStrByLine: "Pisahkan teks dengan baris baru"
_splitStrByLine:
arg1: "Teks"
ref: "Variabel"
aiScriptVar: "Variabel AiScript"
fn: "Fungsi"
_fn:
slots: "Slot"
slots-info: "Pisahkan setiap slot dengan baris baru"
arg1: "Keluaran"
for: "Ulangi"
_for:
arg1: "Jumlah angka untuk diulangi"
arg2: "Aksi"
typeError: "Slot {slot} menerima tipe \"{expect}\", sayangnya nilai yang disediakan adalah \"{actual}\"!"
thereIsEmptySlot: "Slot {slot} kosong!"
types:
string: "Teks"
number: "Angka"
boolean: "Markah"
array: "Daftar"
stringArray: "Daftar teks"
emptySlot: "Slot kosong"
enviromentVariables: "Variabel Lingkungan"
pageVariables: "Elemen halaman"
argVariables: "Masukan slot"
_relayStatus:
requesting: "Menunggu"
accepted: "Disetujui"

View File

@ -1227,8 +1227,6 @@ _pages:
liked: "Pagine che mi piacciono"
featured: "Popolari"
contents: "Contenuto"
content: "Blocco di pagina"
variables: "Variabili"
title: "Titolo"
url: "URL della pagina"
summary: "Riassunto di pagina"
@ -1238,172 +1236,6 @@ _pages:
fontSansSerif: "Sans serif"
eyeCatchingImageSet: "Imposta un'immagine attrattiva"
eyeCatchingImageRemove: "Elimina l'immagine attrattiva"
chooseBlock: "Aggiungi blocco"
selectType: "Seleziona tipo"
enterVariableName: "Digita un nome di variabile"
variableNameIsAlreadyUsed: "Esiste già una variabile con lo stesso nome"
contentBlocks: "Contenuto"
inputBlocks: "Blocchi di input"
specialBlocks: "Speciale"
blocks:
text: "Testo"
textarea: "Area di testo"
section: "Sezione"
image: "Immagini"
button: "Pulsante"
if: "Se"
_if:
variable: "Variabili"
post: "Finestra di pubblicazione"
_post:
text: "Contenuto"
textInput: "Immissione testo"
_textInput:
name: "Nome della variabile"
text: "Titolo"
default: "Valore predefinito"
textareaInput: "Immissione testo a più righe"
_textareaInput:
name: "Nome della variabile"
text: "Titolo"
default: "Valore predefinito"
numberInput: "Immissione numerica"
_numberInput:
name: "Nome della variabile"
text: "Titolo"
default: "Valore predefinito"
_canvas:
width: "Larghezza"
height: "Altezza"
note: "Nota integrata"
_note:
id: "ID nota"
idDescription: "Qui puoi anche incollare l'URL della nota che vuoi impostare."
detailed: "Visualizzazione dettagliata"
switch: "Interruttore"
_switch:
name: "Nome della variabile"
text: "Titolo"
default: "Valore predefinito"
counter: "Contatore"
_counter:
name: "Nome della variabile"
text: "Titolo"
inc: "Valore da aggiungere"
_button:
text: "Titolo"
colored: "Colorato"
action: "Operazione da eseguire quando viene premuto il pulsante"
_action:
dialog: "Visualizzare una finestra di dialogo"
_dialog:
content: "Contenuto"
resetRandom: "Ripristinare un numero aleatorio"
pushEvent: "Inviare evento"
_pushEvent:
event: "Nome evento"
message: "Messaggio da visualizzare quando abilitato"
variable: "Variabile da inviare"
no-variable: "Nessun contenuto"
callAiScript: "Chiamare AiScript"
_callAiScript:
functionName: "Nome della funzione"
radioButton: "Opzioni"
_radioButton:
name: "Nome della variabile"
title: "Titolo"
default: "Valore predefinito"
script:
categories:
comparison: "Metodo comparativo"
random: "Aleatorietà"
value: "Valore"
fn: "Funzione"
list: "Liste"
blocks:
text: "Testo"
multiLineText: "Testo (a più righe)"
textList: "Lista di testo"
_strLen:
arg1: "Testo"
_strPick:
arg1: "Testo"
_strReplace:
arg1: "Testo"
_strReverse:
arg1: "Testo"
_join:
arg1: "Liste"
_add:
arg1: "A"
arg2: "B"
_subtract:
arg1: "A"
arg2: "B"
_multiply:
arg1: "A"
arg2: "B"
_divide:
arg1: "A"
arg2: "B"
_mod:
arg1: "A"
arg2: "B"
_eq:
arg1: "A"
arg2: "B"
notEq: "A e B sono differenti"
_notEq:
arg1: "A"
arg2: "B"
and: "A e B"
_and:
arg1: "A"
arg2: "B"
or: "A o B"
_or:
arg1: "A"
arg2: "B"
_lt:
arg1: "A"
arg2: "B"
_gt:
arg1: "A"
arg2: "B"
_ltEq:
arg1: "A"
arg2: "B"
_gtEq:
arg1: "A"
arg2: "B"
_if:
arg1: "Se"
arg2: "Se"
random: "Aleatorietà"
_randomPick:
arg1: "Liste"
_dailyRandomPick:
arg1: "Liste"
_seedRandom:
arg2: "Probabilità"
_seedRandomPick:
arg2: "Liste"
_DRPWPM:
arg1: "Lista di testo"
_pick:
arg1: "Liste"
_listLen:
arg1: "Liste"
_stringToNumber:
arg1: "Testo"
_splitStrByLine:
arg1: "Testo"
ref: "Variabili"
fn: "Funzione"
types:
string: "Testo"
array: "Liste"
stringArray: "Lista di testo"
_relayStatus:
requesting: "In attesa di approvazione"
accepted: "Approvato"

View File

@ -1384,10 +1384,7 @@ _pages:
my: "自分のページ"
liked: "いいねしたページ"
featured: "人気"
inspector: "インスペクター"
contents: "コンテンツ"
content: "ページブロック"
variables: "変数"
title: "タイトル"
url: "ページURL"
summary: "ページの要約"
@ -1398,274 +1395,6 @@ _pages:
fontSansSerif: "サンセリフ"
eyeCatchingImageSet: "アイキャッチ画像を設定"
eyeCatchingImageRemove: "アイキャッチ画像を削除"
chooseBlock: "ブロックを追加"
selectType: "種類を選択"
enterVariableName: "変数名を決めてください"
variableNameIsAlreadyUsed: "その変数名は既に使われています"
contentBlocks: "コンテンツ"
inputBlocks: "入力"
specialBlocks: "特殊"
blocks:
text: "テキスト"
textarea: "テキストエリア"
section: "セクション"
image: "画像"
button: "ボタン"
if: "もし"
_if:
variable: "変数"
post: "投稿フォーム"
_post:
text: "内容"
attachCanvasImage: "キャンバスの画像を添付する"
canvasId: "キャンバスID"
textInput: "テキスト入力"
_textInput:
name: "変数名"
text: "タイトル"
default: "デフォルト値"
textareaInput: "複数行テキスト入力"
_textareaInput:
name: "変数名"
text: "タイトル"
default: "デフォルト値"
numberInput: "数値入力"
_numberInput:
name: "変数名"
text: "タイトル"
default: "デフォルト値"
canvas: "キャンバス"
_canvas:
id: "キャンバスID"
width: "幅"
height: "高さ"
note: "ノート埋め込み"
_note:
id: "ートID"
idDescription: "ートURLをペーストして設定することもできます。"
detailed: "詳細な表示"
switch: "スイッチ"
_switch:
name: "変数名"
text: "タイトル"
default: "デフォルト値"
counter: "カウンター"
_counter:
name: "変数名"
text: "タイトル"
inc: "増加値"
_button:
text: "タイトル"
colored: "色付き"
action: "ボタンを押したときの動作"
_action:
dialog: "ダイアログを表示する"
_dialog:
content: "内容"
resetRandom: "乱数をリセット"
pushEvent: "イベントを送信させる"
_pushEvent:
event: "イベント名"
message: "押したときに表示するメッセージ"
variable: "送信する変数"
no-variable: "なし"
callAiScript: "AiScript呼び出し"
_callAiScript:
functionName: "関数名"
radioButton: "選択肢"
_radioButton:
name: "変数名"
title: "タイトル"
values: "改行で区切った選択肢"
default: "デフォルト値"
script:
categories:
flow: "制御"
logical: "論理演算"
operation: "計算"
comparison: "比較"
random: "ランダム"
value: "値"
fn: "関数"
text: "テキスト操作"
convert: "変換"
list: "リスト"
blocks:
text: "テキスト"
multiLineText: "テキスト(複数行)"
textList: "テキストのリスト"
_textList:
info: "ひとつひとつを改行で区切ってください"
strLen: "テキストの長さ"
_strLen:
arg1: "テキスト"
strPick: "文字取り出し"
_strPick:
arg1: "テキスト"
arg2: "文字の位置"
strReplace: "テキスト置き換え"
_strReplace:
arg1: "テキスト"
arg2: "置き換え前"
arg3: "置き換え後"
strReverse: "テキストを反転"
_strReverse:
arg1: "テキスト"
join: "テキストを連結"
_join:
arg1: "リスト"
arg2: "区切り"
add: "足す"
_add:
arg1: "A"
arg2: "B"
subtract: "引く"
_subtract:
arg1: "A"
arg2: "B"
multiply: "掛ける"
_multiply:
arg1: "A"
arg2: "B"
divide: "割る"
_divide:
arg1: "A"
arg2: "B"
mod: "割った余り"
_mod:
arg1: "A"
arg2: "B"
round: "小数を丸める"
_round:
arg1: "数値"
eq: "AとBが同じ"
_eq:
arg1: "A"
arg2: "B"
notEq: "AとBが異なる"
_notEq:
arg1: "A"
arg2: "B"
and: "AかつB"
_and:
arg1: "A"
arg2: "B"
or: "AまたはB"
_or:
arg1: "A"
arg2: "B"
lt: "< AがBより小さい"
_lt:
arg1: "A"
arg2: "B"
gt: "> AがBより大きい"
_gt:
arg1: "A"
arg2: "B"
ltEq: "<= AがBと同じか小さい"
_ltEq:
arg1: "A"
arg2: "B"
gtEq: ">= AがBと同じか大きい"
_gtEq:
arg1: "A"
arg2: "B"
if: "分岐"
_if:
arg1: "もし"
arg2: "なら"
arg3: "そうでなければ"
not: "否定"
_not:
arg1: "否定"
random: "ランダム"
_random:
arg1: "確率"
rannum: "乱数"
_rannum:
arg1: "最小"
arg2: "最大"
randomPick: "リストからランダムに選択"
_randomPick:
arg1: "リスト"
dailyRandom: "ランダム (ユーザーごとに日替わり)"
_dailyRandom:
arg1: "確率"
dailyRannum: "乱数 (ユーザーごとに日替わり)"
_dailyRannum:
arg1: "最小"
arg2: "最大"
dailyRandomPick: "リストからランダムに選択 (ユーザーごとに日替わり)"
_dailyRandomPick:
arg1: "リスト"
seedRandom: "ランダム (シード)"
_seedRandom:
arg1: "シード"
arg2: "確率"
seedRannum: "乱数 (シード)"
_seedRannum:
arg1: "シード"
arg2: "最小"
arg3: "最大"
seedRandomPick: "リストからランダムに選択 (シード)"
_seedRandomPick:
arg1: "シード"
arg2: "リスト"
DRPWPM: "確率付きリストからランダムに選択 (ユーザーごとに日替わり)"
_DRPWPM:
arg1: "テキストのリスト"
pick: "リストから選択"
_pick:
arg1: "リスト"
arg2: "位置"
listLen: "リストの長さを取得"
_listLen:
arg1: "リスト"
number: "数値"
stringToNumber: "テキストを数値に"
_stringToNumber:
arg1: "テキスト"
numberToString: "数値をテキストに"
_numberToString:
arg1: "数値"
splitStrByLine: "テキストを行で分割"
_splitStrByLine:
arg1: "テキスト"
ref: "変数"
aiScriptVar: "AiScript変数"
fn: "関数"
_fn:
slots: "スロット"
slots-info: "スロットひとつひとつを改行で区切ってください"
arg1: "出力"
for: "繰り返し"
_for:
arg1: "回数"
arg2: "処理"
typeError: "スロット{slot}は\"{expect}\"を受け付けますが、\"{actual}\"が入れられています!"
thereIsEmptySlot: "スロット{slot}が空です!"
types:
string: "テキスト"
number: "数値"
boolean: "フラグ"
array: "リスト"
stringArray: "テキストのリスト"
emptySlot: "空のスロット"
enviromentVariables: "環境変数"
pageVariables: "ページ要素"
argVariables: "入力スロット"
_relayStatus:
requesting: "承認待ち"

View File

@ -936,252 +936,6 @@ _pages:
fontSansSerif: "サンセリフ"
eyeCatchingImageSet: "アイキャッチ画像を設定"
eyeCatchingImageRemove: "アイキャッチ画像を削除"
chooseBlock: "ブロックを追加"
selectType: "種類を選択"
contentBlocks: "コンテンツ"
inputBlocks: "入力"
specialBlocks: "特殊"
blocks:
text: "テキスト"
textarea: "テキストエリア"
section: "セクション"
image: "画像"
button: "ボタン"
if: "もし"
_if:
variable: "変数"
post: "投稿フォーム"
_post:
text: "内容"
canvasId: "キャンバスID"
textInput: "テキスト入力"
_textInput:
name: "変数名"
text: "タイトル"
default: "デフォルト値"
textareaInput: "複数行テキスト入力"
_textareaInput:
name: "変数名"
text: "タイトル"
default: "デフォルト値"
numberInput: "数値入力"
_numberInput:
name: "変数名"
text: "タイトル"
default: "デフォルト値"
canvas: "キャンバス"
_canvas:
id: "キャンバスID"
width: "幅"
height: "高さ"
note: "ノート埋め込み"
_note:
id: "ートID"
detailed: "詳細な表示"
switch: "スイッチ"
_switch:
name: "変数名"
text: "タイトル"
default: "デフォルト値"
counter: "カウンター"
_counter:
name: "変数名"
text: "タイトル"
inc: "増加値"
_button:
text: "タイトル"
colored: "色付き"
action: "ボタンを押したときの動作"
_action:
dialog: "ダイアログを表示する"
_dialog:
content: "内容"
resetRandom: "乱数をリセット"
pushEvent: "イベントを送信させる"
_pushEvent:
event: "イベント名"
no-variable: "なし"
callAiScript: "AiScript呼び出し"
_callAiScript:
functionName: "関数名"
radioButton: "選択肢"
_radioButton:
name: "変数名"
title: "タイトル"
values: "改行で区切った選択肢"
default: "デフォルト値"
script:
categories:
flow: "制御"
logical: "論理演算"
operation: "計算"
comparison: "比較"
random: "ランダム"
value: "値"
fn: "関数"
text: "関数"
convert: "変換"
list: "リスト"
blocks:
text: "テキスト"
multiLineText: "テキスト(複数行)"
textList: "テキストのリスト"
strLen: "テキストの長さ"
_strLen:
arg1: "テキスト"
strPick: "文字取り出し"
_strPick:
arg1: "テキスト"
arg2: "文字の位置"
strReplace: "テキスト置き換え"
_strReplace:
arg1: "テキスト"
arg2: "置き換え前"
arg3: "置き換え後"
strReverse: "テキストを反転"
_strReverse:
arg1: "テキスト"
join: "テキストを連結"
_join:
arg1: "リスト"
arg2: "区切り"
add: "足す"
_add:
arg1: "A"
arg2: "B"
subtract: "引く"
_subtract:
arg1: "A"
arg2: "A"
multiply: "掛ける"
_multiply:
arg1: "A"
arg2: "B"
divide: "割る"
_divide:
arg1: "A"
arg2: "B"
mod: "割った余り"
_mod:
arg1: "A"
arg2: "B"
round: "小数を丸める"
_round:
arg1: "数値"
eq: "AとBが同じ"
_eq:
arg1: "A"
arg2: "B"
notEq: "AとBが異なる"
_notEq:
arg1: "A"
arg2: "B"
and: "AかつB"
_and:
arg1: "A"
arg2: "B"
or: "AまたはB"
_or:
arg1: "A"
arg2: "B"
lt: "< AがBより小さい"
_lt:
arg1: "A"
arg2: "B"
gt: "> AがBより大きい"
_gt:
arg1: "A"
arg2: "B"
ltEq: "<= AがBと同じか小さい"
_ltEq:
arg1: "A"
arg2: "B"
gtEq: ">= AがBと同じか大きい"
_gtEq:
arg1: "A"
arg2: "B"
if: "分岐"
_if:
arg1: "もし"
arg2: "なら"
arg3: "そうでなければ"
not: "否定"
_not:
arg1: "否定"
random: "ランダム"
_random:
arg1: "確率"
rannum: "乱数"
_rannum:
arg1: "最小"
arg2: "最大"
randomPick: "リストからランダムに選ぶ"
_randomPick:
arg1: "リスト"
dailyRandom: "ランダム (ユーザーごとに日替わり)"
_dailyRandom:
arg1: "確率"
dailyRannum: "乱数 (ユーザーごとに日替わり)"
_dailyRannum:
arg1: "最小"
arg2: "最大"
dailyRandomPick: "リストからランダムに選ぶ (ユーザーごとに日替わり)"
_dailyRandomPick:
arg1: "リスト"
seedRandom: "ランダム (シード)"
_seedRandom:
arg1: "シード"
arg2: "確率"
seedRannum: "乱数 (シード)"
_seedRannum:
arg1: "シード"
arg2: "最小"
arg3: "最大"
seedRandomPick: "リストからランダムに選択 (シード)"
_seedRandomPick:
arg1: "シード"
arg2: "リスト"
DRPWPM: "確率付きリストからランダムに選ぶ (ユーザーごとに日替わり)"
_DRPWPM:
arg1: "テキストのリスト"
pick: "リストから選ぶ"
_pick:
arg1: "リスト"
arg2: "位置"
listLen: "リストの長さを取得"
_listLen:
arg1: "リスト"
number: "数値"
stringToNumber: "テキストを数値に"
_stringToNumber:
arg1: "テキスト"
numberToString: "数値をテキストに"
_numberToString:
arg1: "数値"
splitStrByLine: "テキストを行で分割"
_splitStrByLine:
arg1: "テキスト"
ref: "変数"
aiScriptVar: "AiScript変数"
fn: "関数"
_fn:
slots: "スロット"
arg1: "出力"
for: "繰り返し"
_for:
arg1: "回数"
arg2: "処理"
thereIsEmptySlot: "スロット{slot}が空っぽやで!"
types:
string: "テキスト"
number: "数値"
boolean: "フラグ"
array: "リスト"
stringArray: "テキストのリスト"
emptySlot: "空のスロット"
enviromentVariables: "環境変数"
pageVariables: "ページ要素"
argVariables: "入力スロット"
_notification:
fileUploaded: "ファイルが無事アップロードされたで。"
youGotMention: "{name}からのメンション"

View File

@ -88,28 +88,6 @@ _pages:
fontSerif: "Serif"
fontSansSerif: "Sans Serif"
eyeCatchingImageRemove: "Kkes tugna i d-ijebden"
selectType: "Fren anaw"
contentBlocks: "Agbur"
inputBlocks: "Anekcum"
specialBlocks: "Uzzig"
script:
categories:
list: "Tibdarin"
blocks:
_join:
arg1: "Tibdarin"
_randomPick:
arg1: "Tibdarin"
_dailyRandomPick:
arg1: "Tibdarin"
_seedRandomPick:
arg2: "Tibdarin"
_pick:
arg1: "Tibdarin"
_listLen:
arg1: "Tibdarin"
types:
array: "Tibdarin"
_notification:
youWereFollowed: "Yeṭṭafaṛ-ik·em-id"
_types:

View File

@ -1327,10 +1327,7 @@ _pages:
my: "내 페이지"
liked: "좋아요한 페이지"
featured: "인기"
inspector: "인스펙터"
contents: "콘텐츠"
content: "페이지 블록"
variables: "변수"
title: "제목"
url: "페이지 URL"
summary: "페이지 요약"
@ -1341,262 +1338,6 @@ _pages:
fontSansSerif: "고딕체"
eyeCatchingImageSet: "아이캐치 이미지를 설정"
eyeCatchingImageRemove: "아이캐치 이미지를 삭제"
chooseBlock: "블록 추가"
selectType: "종류 선택"
enterVariableName: "변수명을 지정해주세요"
variableNameIsAlreadyUsed: "해당 변수명은 이미 사용중입니다"
contentBlocks: "콘텐츠"
inputBlocks: "입력"
specialBlocks: "특수"
blocks:
text: "텍스트"
textarea: "텍스트 영역"
section: "섹션"
image: "이미지"
button: "버튼"
if: "조건문"
_if:
variable: "변수"
post: "글 입력란"
_post:
text: "내용"
attachCanvasImage: "캔버스의 이미지와 함께 게시하기"
canvasId: "캔버스 ID"
textInput: "텍스트 입력"
_textInput:
name: "변수명"
text: "제목"
default: "기본값"
textareaInput: "여러 줄 텍스트 입력"
_textareaInput:
name: "변수명"
text: "제목"
default: "기본값"
numberInput: "수치 입력"
_numberInput:
name: "변수명"
text: "제목"
default: "기본값"
canvas: "캔버스"
_canvas:
id: "캔버스 ID"
width: "폭"
height: "높이"
note: "노트필기"
_note:
id: "노트 ID"
idDescription: "노트 URL을 붙여넣어 설정할 수도 있습니다."
detailed: "세부 정보 보기"
switch: "스위치"
_switch:
name: "변수명"
text: "제목"
default: "기본값"
counter: "카운터"
_counter:
name: "변수명"
text: "제목"
inc: "증가치"
_button:
text: "제목"
colored: "색 입히기"
action: "버튼을 눌렀을 때의 동작"
_action:
dialog: "대화상자를 표시"
_dialog:
content: "내용"
resetRandom: "난수를 초기화"
pushEvent: "이벤트 보내기"
_pushEvent:
event: "이벤트 이름"
message: "눌렀을 때 표시할 페이지"
variable: "보낼 변수"
no-variable: "없음"
callAiScript: "AiScript 호출"
_callAiScript:
functionName: "함수명"
radioButton: "선택지"
_radioButton:
name: "변수명"
title: "제목"
values: "줄바꿈으로 구분된 선택지"
default: "기본값"
script:
categories:
flow: "흐름 제어"
logical: "논리 연산"
operation: "계산"
comparison: "비교"
random: "랜덤"
value: "값"
fn: "함수"
text: "텍스트 조작"
convert: "변환"
list: "리스트"
blocks:
text: "텍스트"
multiLineText: "텍스트 (여러 줄)"
textList: "텍스트 목록"
_textList:
info: "각각을 줄바꿈으로 구분해주세요"
strLen: "텍스트의 길이"
_strLen:
arg1: "텍스트"
strPick: "문자 추출"
_strPick:
arg1: "텍스트"
arg2: "문자 위치"
strReplace: "텍스트 대체"
_strReplace:
arg1: "텍스트"
arg2: "대체될 텍스트"
arg3: "대체할 텍스트"
strReverse: "텍스트 뒤집기"
_strReverse:
arg1: "텍스트"
join: "텍스트 합치기"
_join:
arg1: "리스트"
arg2: "구분자"
add: "더하기"
_add:
arg1: "A"
arg2: "B"
subtract: "빼기"
_subtract:
arg1: "A"
arg2: "B"
multiply: "곱하기"
_multiply:
arg1: "A"
arg2: "B"
divide: "나누기"
_divide:
arg1: "A"
arg2: "B"
mod: "나눈 나머지"
_mod:
arg1: "A"
arg2: "B"
round: "소수점을 반올림"
_round:
arg1: "수치"
eq: "A와 B가 동일"
_eq:
arg1: "A"
arg2: "B"
notEq: "A와 B가 다름"
_notEq:
arg1: "A"
arg2: "B"
and: "A와 B가 둘 다 참"
_and:
arg1: "A"
arg2: "B"
or: "A, B중 하나 이상이 참"
_or:
arg1: "A"
arg2: "B"
lt: "< A가 B보다 작음"
_lt:
arg1: "A"
arg2: "B"
gt: "> A가 B보다 큼"
_gt:
arg1: "A"
arg2: "B"
ltEq: "<= A가 B보다 작거나 같음"
_ltEq:
arg1: "A"
arg2: "B"
gtEq: ">= A가 B보다 크거나 같음"
_gtEq:
arg1: "A"
arg2: "B"
if: "분기"
_if:
arg1: "조건문"
arg2: "참일 경우"
arg3: "거짓일 경우"
not: "부정"
_not:
arg1: "부정"
random: "랜덤"
_random:
arg1: "확률"
rannum: "난수"
_rannum:
arg1: "최솟값"
arg2: "최댓값"
randomPick: "목록에서 임의로 선택"
_randomPick:
arg1: "리스트"
dailyRandom: "랜덤 (하루동안 결과 유지)"
_dailyRandom:
arg1: "확률"
dailyRannum: "난수 (하루동안 결과 유지)"
_dailyRannum:
arg1: "최솟값"
arg2: "최댓값"
dailyRandomPick: "목록에서 임의로 선택 (하루동안 결과 유지)"
_dailyRandomPick:
arg1: "리스트"
seedRandom: "무작위 (시드)"
_seedRandom:
arg1: "시드"
arg2: "확률"
seedRannum: "난수 (시드)"
_seedRannum:
arg1: "시드"
arg2: "최솟값"
arg3: "최댓값"
seedRandomPick: "목록에서 무작위로 선택 (시드)"
_seedRandomPick:
arg1: "시드"
arg2: "리스트"
DRPWPM: "확률형 목록에서 임의로 선택 (하루동안 결과 유지)"
_DRPWPM:
arg1: "텍스트 목록"
pick: "목록에서 선택"
_pick:
arg1: "리스트"
arg2: "위치"
listLen: "리스트의 길이 가져오기"
_listLen:
arg1: "리스트"
number: "수치"
stringToNumber: "텍스트를 수치로"
_stringToNumber:
arg1: "텍스트"
numberToString: "수치를 텍스트로"
_numberToString:
arg1: "수치"
splitStrByLine: "텍스트를 행 단위로 분할"
_splitStrByLine:
arg1: "텍스트"
ref: "변수"
aiScriptVar: "AiScript 변수"
fn: "함수"
_fn:
slots: "슬롯"
slots-info: "각 슬롯을 줄바꿈으로 구분하여 주세요"
arg1: "출력"
for: "반복"
_for:
arg1: "횟수"
arg2: "처리"
typeError: "슬롯 {slot}은 \"{expect}\"를 사용할 수 있지만 \"{actual}이 들어있습니다!"
thereIsEmptySlot: "슬롯 {slot}이(가) 비었습니다!"
types:
string: "텍스트"
number: "수치"
boolean: "플래그"
array: "리스트"
stringArray: "텍스트 목록"
emptySlot: "빈 슬롯"
enviromentVariables: "환경 변수"
pageVariables: "페이지 요소"
argVariables: "입력 슬롯"
_relayStatus:
requesting: "대기 중"
accepted: "승인됨"

View File

@ -344,27 +344,6 @@ _charts:
federation: "Federatie"
_timelines:
home: "Startpagina"
_pages:
blocks:
image: "Afbeeldingen"
script:
categories:
list: "Lijsten"
blocks:
_join:
arg1: "Lijsten"
_randomPick:
arg1: "Lijsten"
_dailyRandomPick:
arg1: "Lijsten"
_seedRandomPick:
arg2: "Lijsten"
_pick:
arg1: "Lijsten"
_listLen:
arg1: "Lijsten"
types:
array: "Lijsten"
_notification:
youWereFollowed: "volgde jou"
_types:

View File

@ -1117,10 +1117,7 @@ _pages:
my: "Moje strony"
liked: "Polubione strony"
featured: "Wyróżnione"
inspector: "Inspektor"
contents: "Zawartość"
content: "Blokada strony"
variables: "Zmienne"
title: "Tytuł"
url: "URL strony"
summary: "Podsumowanie strony"
@ -1131,243 +1128,6 @@ _pages:
fontSansSerif: "Bezszeryfowa"
eyeCatchingImageSet: "Ustaw przyciągające wzrok zdjęcie"
eyeCatchingImageRemove: "Usuń przyciągające wzrok zdjęcie"
chooseBlock: "Dodaj blok"
selectType: "Wybierz typ"
enterVariableName: "Wprowadź nazwę dla swojej zmiennej"
variableNameIsAlreadyUsed: "Ta nazwa jest już używana przez inną zmienną"
contentBlocks: "Zawartość"
inputBlocks: "Wejście"
specialBlocks: "Specjalne"
blocks:
text: "Tekst"
textarea: "Pole tekstowe"
section: "Sekcja"
image: "Zdjęcia"
button: "Przycisk"
if: "Jeżeli"
_if:
variable: "Zmienna"
post: "Utwórz wpis"
_post:
text: "Treść"
textInput: "Pole tekstowe"
_textInput:
name: "Nazwa zmiennej"
text: "Tytuł"
default: "Domyślna wartość"
textareaInput: "Pole tekstowe na wiele wierszy"
_textareaInput:
name: "Nazwa zmiennej"
text: "Tytuł"
default: "Domyślna wartość"
numberInput: "Pole na liczbę"
_numberInput:
name: "Nazwa zmiennej"
text: "Tytuł"
default: "Domyślna wartość"
_canvas:
width: "Szerokość"
height: "Wysokość"
note: "Osadzony wpis"
_note:
id: "ID wpisu"
idDescription: "Możesz też wkleić adres URL wpisu, aby go ustawić."
detailed: "Szczegółowy widok"
switch: "Przełącznik"
_switch:
name: "Nazwa zmiennej"
text: "Tytuł"
default: "Domyślna wartość"
counter: "Licznik"
_counter:
name: "Nazwa zmiennej"
text: "Tytuł"
inc: "Zwiększ o"
_button:
text: "Tytuł"
colored: "Kolorowe"
action: "Działanie wykonywane przy naciśnięciu przycisku"
_action:
dialog: "Pokazuj okno dialogowe"
_dialog:
content: "Treść"
resetRandom: "Resetuj losowe ziarno"
pushEvent: "Wyślij zdarzenie"
_pushEvent:
event: "Nazwa zdarzenia"
message: "Wiadomość do wyświetlenia po aktywowaniu"
variable: "Zmienna do wysłania"
no-variable: "Brak"
callAiScript: "Wywołaj AiScript"
_callAiScript:
functionName: "Nazwa funkcji"
radioButton: "Wybór"
_radioButton:
name: "Nazwa zmiennej"
title: "Tytuł"
values: "Lista wyborów (oddzielonych znakiem nowego wiersza)"
default: "Domyślna wartość"
script:
categories:
flow: "Kontrola przepływu"
logical: "Operacje logiczne"
operation: "Obliczanie"
comparison: "Porównanie"
random: "Losowe"
value: "Wartość"
fn: "Funkcje"
text: "Działania na tekście"
convert: "Transformacja"
list: "Listy"
blocks:
text: "Tekst"
multiLineText: "Tekst (w wielu wierszach)"
_textList:
info: "Oddziel każdy wpis znakiem nowego wiersza"
strLen: "Długość tekstu"
_strLen:
arg1: "Tekst"
_strPick:
arg1: "Tekst"
arg2: "Położenie znaku"
strReplace: "Zamiana tekstu"
_strReplace:
arg1: "Tekst"
arg2: "Tekst do zamiany"
arg3: "Zamieniono z"
_strReverse:
arg1: "Tekst"
_join:
arg1: "Listy"
arg2: "Odstęp"
add: "Dodaj"
_add:
arg1: "A"
arg2: "B"
subtract: "Odejmij"
_subtract:
arg1: "A"
arg2: "B"
multiply: "Pomnóż"
_multiply:
arg1: "A"
arg2: "B"
divide: "Podziel"
_divide:
arg1: "A"
arg2: "B"
mod: "Reszta"
_mod:
arg1: "A"
arg2: "B"
_round:
arg1: "Liczba"
eq: "A i B są sobie równe"
_eq:
arg1: "A"
arg2: "B"
notEq: "A i B różnią się"
_notEq:
arg1: "A"
arg2: "B"
and: "A I B"
_and:
arg1: "A"
arg2: "B"
or: "A LUB B"
_or:
arg1: "A"
arg2: "B"
lt: "< A jest mniejsze niż B"
_lt:
arg1: "A"
arg2: "B"
gt: "> A jest większe od B"
_gt:
arg1: "A"
arg2: "B"
ltEq: "<= A jest mniejsze lub równe B"
_ltEq:
arg1: "A"
arg2: "B"
gtEq: ">= A jest większe lub równe B"
_gtEq:
arg1: "A"
arg2: "B"
if: "Warunek"
_if:
arg1: "Jeżeli"
arg2: "Jeżeli prawda"
not: "NIE"
_not:
arg1: "NIE"
random: "Losowe"
_random:
arg1: "Prawdopodobieństwo"
rannum: "Losowa liczba"
_rannum:
arg1: "Minimalna wartość"
arg2: "Maksymalna wartość"
randomPick: "Wybierz losowo z listy"
_randomPick:
arg1: "Listy"
dailyRandom: "Losowo (zostaje na dzień)"
_dailyRandom:
arg1: "Prawdopodobieństwo"
dailyRannum: "Losowa liczba (zostaje na dzień)"
_dailyRannum:
arg1: "Minimalna wartość"
arg2: "Maksymalna wartość"
dailyRandomPick: "Wybierz losowo z listy (zostaje na dzień)"
_dailyRandomPick:
arg1: "Listy"
seedRandom: "Losowo (z ziarnem)"
_seedRandom:
arg1: "Ziarno"
arg2: "Prawdopodobieństwo"
seedRannum: "Losowa liczba (z ziarnem)"
_seedRannum:
arg1: "Ziarno"
arg2: "Minimalna wartość"
arg3: "Maksymalna wartość"
seedRandomPick: "Wybierz losowo z listy (z ziarnem)"
_seedRandomPick:
arg1: "Ziarno"
arg2: "Listy"
DRPWPM: "Wybierz losowo z ważonej listy (zostaje na dzień)"
pick: "Wybierz z listy"
_pick:
arg1: "Listy"
arg2: "Położenie"
listLen: "Uzyskaj długość listy"
_listLen:
arg1: "Listy"
number: "Liczba"
stringToNumber: "Tekst na liczbę"
_stringToNumber:
arg1: "Tekst"
numberToString: "Liczba na tekst"
_numberToString:
arg1: "Liczba"
splitStrByLine: "Rozdziel tekst znakami nowej linii"
_splitStrByLine:
arg1: "Tekst"
ref: "Zmienne"
aiScriptVar: "Zmienna AiScript"
fn: "Funkcje"
_fn:
arg1: "Wyjście"
for: "Powtórzenie"
_for:
arg1: "Liczba powtórzeń"
arg2: "Działanie"
types:
string: "Tekst"
number: "Liczba"
boolean: "Flaguj"
array: "Listy"
enviromentVariables: "Zmienna środowiskowa"
pageVariables: "Element strony"
_relayStatus:
requesting: "Oczekujące"
accepted: "Zaakceptowano"

View File

@ -190,173 +190,6 @@ _exportOrImport:
muteList: "Silenciar"
blockingList: "Bloquear"
userLists: "Listas"
_pages:
blocks:
_button:
_action:
_pushEvent:
event: "Nome do evento"
message: "Mostrar mensagem quando ativado"
variable: "Variável a mandar"
no-variable: "Nenhum"
callAiScript: "Invocar AiScript"
_callAiScript:
functionName: "Nome da função"
radioButton: "Escolha"
_radioButton:
values: "Lista de escolhas separadas por quebras de texto"
script:
categories:
logical: "Operação lógica"
operation: "Cálculos"
comparison: "Comparação"
list: "Listas"
blocks:
_strReplace:
arg2: "Texto que irá ser substituído"
arg3: "Substituir com"
strReverse: "Virar texto"
join: "Sequência de texto"
_join:
arg1: "Listas"
arg2: "Separador"
add: "Somar"
_add:
arg1: "A"
arg2: "B"
subtract: "Subtrair"
_subtract:
arg1: "A"
arg2: "B"
multiply: "Multiplicar"
_multiply:
arg1: "A"
arg2: "B"
divide: "Dividir"
_divide:
arg1: "A"
arg2: "B"
mod: "O resto de"
_mod:
arg1: "A"
arg2: "B"
round: "Arredondar decimal"
_round:
arg1: "Numérico"
eq: "A e B são iguais"
_eq:
arg1: "A"
arg2: "B"
notEq: "A e B são diferentes"
_notEq:
arg1: "A"
arg2: "B"
and: "A e B"
_and:
arg1: "A"
arg2: "B"
or: "A OU B"
_or:
arg1: "A"
arg2: "B"
lt: "< A é menor do que B"
_lt:
arg1: "A"
arg2: "B"
gt: "> A é maior do que B"
_gt:
arg1: "A"
arg2: "B"
ltEq: "<= A é maior ou igual a B"
_ltEq:
arg1: "A"
arg2: "B"
gtEq: ">= A é maior ou igual a B"
_gtEq:
arg1: "A"
arg2: "B"
if: "Galho"
_if:
arg1: "Se"
arg2: "Então"
arg3: "Se não"
not: "NÃO"
_not:
arg1: "NÃO"
random: "Aleatório"
_random:
arg1: "Probabilidade"
rannum: "Numeral aleatório"
_rannum:
arg1: "Valor mínimo"
arg2: "Valor máximo"
randomPick: "Escolher aleatoriamente de uma lista"
_randomPick:
arg1: "Listas"
dailyRandom: "Aleatório (Muda uma vez por dia para cada usuário)"
_dailyRandom:
arg1: "Probabilidade"
dailyRannum: "Numeral aleatório (Muda uma vez por dia para cada usuário)"
_dailyRannum:
arg1: "Valor mínimo"
arg2: "Valor máximo"
dailyRandomPick: "Escolher aleatoriamente de uma lista (Muda uma vez por dia para cada usuário)"
_dailyRandomPick:
arg1: "Listas"
seedRandom: "Aleatório (com semente)"
_seedRandom:
arg1: "Semente"
arg2: "Probabilidade"
seedRannum: "Número aleatório (com semente)"
_seedRannum:
arg1: "Semente"
arg2: "Valor mínimo"
arg3: "Valor máximo"
seedRandomPick: "Escolher aleatoriamente de uma lista (com uma semente)"
_seedRandomPick:
arg1: "Semente"
arg2: "Listas"
DRPWPM: "Escolher aleatoriamente de uma lista ponderada (Muda uma vez por dia para cada usuário)"
_DRPWPM:
arg1: "Lista de texto"
pick: "Escolhe a partir da lista"
_pick:
arg1: "Listas"
arg2: "Posição"
listLen: "Pegar comprimento da lista"
_listLen:
arg1: "Listas"
number: "Numérico"
stringToNumber: "Texto para numérico"
_stringToNumber:
arg1: "Texto"
numberToString: "Numérico para texto"
_numberToString:
arg1: "Numérico"
splitStrByLine: "Dividir texto por quebras"
_splitStrByLine:
arg1: "Texto"
ref: "Variável"
aiScriptVar: "Variável AiScript"
fn: "Função"
_fn:
slots: "Espaços"
slots-info: "Separar cada espaço com uma quebra de texto"
arg1: "Resultado"
for: "Repetição 'for'"
_for:
arg1: "Número de repetições"
arg2: "Ação"
typeError: "Espaço {slot} aceita valores de tipo \"{expect}\", mas o valor dado é do tipo \"{actual}\"!"
thereIsEmptySlot: "O espaço {slot} está vazio!"
types:
string: "Texto"
number: "Numérico"
array: "Listas"
stringArray: "Lista de texto"
emptySlot: "Espaço vazio"
enviromentVariables: "Variáveis de ambiente"
pageVariables: "Variáveis de página"
_relayStatus:
requesting: "Pendente"
accepted: "Aprovado"

View File

@ -684,27 +684,6 @@ _charts:
federation: "Federație"
_timelines:
home: "Acasă"
_pages:
blocks:
image: "Imagini"
script:
categories:
list: "Liste"
blocks:
_join:
arg1: "Liste"
_randomPick:
arg1: "Liste"
_dailyRandomPick:
arg1: "Liste"
_seedRandomPick:
arg2: "Liste"
_pick:
arg1: "Liste"
_listLen:
arg1: "Liste"
types:
array: "Liste"
_notification:
youWereFollowed: "te-a urmărit"
youWereInvitedToGroup: "Ai fost invitat într-un grup"

View File

@ -1310,10 +1310,7 @@ _pages:
my: "Свои страницы"
liked: "Понравившиеся страницы"
featured: "Популярные"
inspector: "Инспектор"
contents: "Содержимое"
content: "Содержимое"
variables: "Переменные"
title: "Заголовок"
url: "Адрес страницы"
summary: "Краткое содержание"
@ -1324,262 +1321,6 @@ _pages:
fontSansSerif: "Гротеск (без засечек)"
eyeCatchingImageSet: "Добавить картинку для привлечения внимания"
eyeCatchingImageRemove: "Убрать картинку для привлечения внимания"
chooseBlock: "Добавить блок"
selectType: "Выберите вид"
enterVariableName: "Ведите имя переменной"
variableNameIsAlreadyUsed: "Это имя уже есть у другой переменной"
contentBlocks: "Содержательные"
inputBlocks: "Для ввода"
specialBlocks: "Особые"
blocks:
text: "Текст"
textarea: "Текст в рамке"
section: "Раздел"
image: "Изображения"
button: "Кнопка"
if: "Условный"
_if:
variable: "Переменная"
post: "Создание заметки"
_post:
text: "Текст"
attachCanvasImage: "Прикрепить изображение с холста"
canvasId: "Метка холста"
textInput: "Поле ввода текста"
_textInput:
name: "Имя переменной"
text: "Подпись"
default: "Исходное содержимое"
textareaInput: "Многострочное поле ввода текста"
_textareaInput:
name: "Имя переменной"
text: "Подпись"
default: "Исходное содержимое"
numberInput: "Поле для ввода числа"
_numberInput:
name: "Имя переменной"
text: "Подпись"
default: "Исходное значение"
canvas: "Холст"
_canvas:
id: "Метка холста"
width: "Ширина"
height: "Высота"
note: "Встроенная заметка"
_note:
id: "Идентификатор заметки"
idDescription: "Можно также вставить ссылку на заметку."
detailed: "Подробный вид"
switch: "Выключатель"
_switch:
name: "Имя переменной"
text: "Подпись"
default: "Исходное содержимое"
counter: "Кнопка со счётчиком"
_counter:
name: "Имя переменной"
text: "Надпись"
inc: "Увеличивать на"
_button:
text: "Надпись"
colored: "Выделена цветом"
action: "Действие по нажатию"
_action:
dialog: "Показать всплывающий текст"
_dialog:
content: "Всплывающий текст"
resetRandom: "Сброс генератора случайности"
pushEvent: "Вызвать событие"
_pushEvent:
event: "Имя события"
message: "Сообщение при нажатии"
variable: "Передать переменную с событием"
no-variable: "нет"
callAiScript: "Вызвать AiScript"
_callAiScript:
functionName: "Имя функции"
radioButton: "Кнопка-переключатель"
_radioButton:
name: "Имя переменной"
title: "Заголовок"
values: "Значения"
default: "Исходное значение"
script:
categories:
flow: "Управление исполнением"
logical: "Логические"
operation: "Арифметические"
comparison: "Сравнение"
random: "Случайные"
value: "Значения"
fn: "Функции"
text: "Текстовые"
convert: "Преобразование"
list: "Список"
blocks:
text: "Строка текста"
multiLineText: "Многострочный текст"
textList: "Список строк текста"
_textList:
info: "Пишите каждый пункт с новой строки"
strLen: "Длина текста"
_strLen:
arg1: "Текст"
strPick: "Взять знак из текста"
_strPick:
arg1: "Текст"
arg2: "Позиция знака"
strReplace: "Замена текста"
_strReplace:
arg1: "Текст, в котором заменять"
arg2: "Заменяемый текст"
arg3: "Менять на"
strReverse: "В обратном порядке"
_strReverse:
arg1: "Текст"
join: "Объединение"
_join:
arg1: "Списки"
arg2: "Разделитель"
add: "Добавить"
_add:
arg1: "A"
arg2: "B"
subtract: "Вычитание"
_subtract:
arg1: "A"
arg2: "B"
multiply: "Умножение"
_multiply:
arg1: "A"
arg2: "B"
divide: "Деление"
_divide:
arg1: "A"
arg2: "B"
mod: "Остаток от деления"
_mod:
arg1: "A"
arg2: "B"
round: "Округление до целого"
_round:
arg1: "Число"
eq: "A равно B"
_eq:
arg1: "А"
arg2: "B"
notEq: "A не равно B"
_notEq:
arg1: "A"
arg2: "B"
and: "A и B"
_and:
arg1: "A"
arg2: "B"
or: "A или B"
_or:
arg1: "A"
arg2: "B"
lt: "A < B (меньше)"
_lt:
arg1: "A"
arg2: "B"
gt: "A > B (больше)"
_gt:
arg1: "A"
arg2: "B"
ltEq: "A ⩽ B (меньше или равно)"
_ltEq:
arg1: "A"
arg2: "B"
gtEq: "A ⩾ B (больше или равно)"
_gtEq:
arg1: "A"
arg2: "B"
if: "Условный"
_if:
arg1: "Условие"
arg2: "Если правда"
arg3: "Если ложь"
not: "Отрицание"
_not:
arg1: "Условие"
random: "Случайность"
_random:
arg1: "Вероятность"
rannum: "Случайное число"
_rannum:
arg1: "Минимум"
arg2: "Максимум"
randomPick: "Случайный выбор из списка"
_randomPick:
arg1: "Списки"
dailyRandom: "Случайность (на день для пользователя)"
_dailyRandom:
arg1: "Вероятность"
dailyRannum: "Случайное число (на день для пользователя)"
_dailyRannum:
arg1: "Минимум"
arg2: "Максимум"
dailyRandomPick: "Случайный выбор из списка (на день для пользователя)"
_dailyRandomPick:
arg1: "Списки"
seedRandom: "Псевдослучайность (заданная зерном)"
_seedRandom:
arg1: "Зерно"
arg2: "Вероятность"
seedRannum: "Псевдослучайное число (заданное зерном)"
_seedRannum:
arg1: "Зерно"
arg2: "Минимум"
arg3: "Максимум"
seedRandomPick: "Псевдослучайный выбор из списка (заданный зерном)"
_seedRandomPick:
arg1: "Зерно"
arg2: "Списки"
DRPWPM: "Случайный выбор из взвешенного списка (на день для пользователя)"
_DRPWPM:
arg1: "Список строк текста"
pick: "Выбор из списка"
_pick:
arg1: "Списки"
arg2: "Индекс"
listLen: "Количество элементов в списке"
_listLen:
arg1: "Списки"
number: "Число"
stringToNumber: "Число из текста"
_stringToNumber:
arg1: "Текст"
numberToString: "Число в текст"
_numberToString:
arg1: "Число"
splitStrByLine: "Разделение текста на строки"
_splitStrByLine:
arg1: "Текст"
ref: "Переменная"
aiScriptVar: "Переменная AiScript"
fn: "Свои функции"
_fn:
slots: "Аргументы"
slots-info: "Напишите имя каждого аргумента с новой строки"
arg1: "Формула"
for: "Цикл"
_for:
arg1: "Количество повторений"
arg2: "Действие"
typeError: "Аргумент {slot} должен быть иметь тип «{expect}», а передали «{actual}»!"
thereIsEmptySlot: "Аргумент {slot} не заполнен!"
types:
string: "Текст"
number: "Число"
boolean: "Логический"
array: "Списки"
stringArray: "Список строк текста"
emptySlot: "Пустой аргумент"
enviromentVariables: "Переменная окружения"
pageVariables: "Элемент страницы"
argVariables: "Аргументы"
_relayStatus:
requesting: "В ожидании одобрения"
accepted: "Одобрено."

View File

@ -1324,10 +1324,7 @@ _pages:
my: "Moje stránky"
liked: "Obľúbené stránky"
featured: "Význačné"
inspector: "Inšpektor"
contents: "Obsah"
content: "Blok stránky"
variables: "Premenné"
title: "Nadpis"
url: "URL stránky"
summary: "Zhrnutie stránky"
@ -1338,262 +1335,6 @@ _pages:
fontSansSerif: "Bezpätkové"
eyeCatchingImageSet: "Nastaviť miniatúru"
eyeCatchingImageRemove: "Odstrániť miniatúru"
chooseBlock: "Pridať blok"
selectType: "Vyberte typ"
enterVariableName: "Zadajte meno premennej"
variableNameIsAlreadyUsed: "Meno premennej s už používa"
contentBlocks: "Obsah"
inputBlocks: "Vstup"
specialBlocks: "Špeciálne"
blocks:
text: "Text"
textarea: "Textové pole"
section: "Sekcia"
image: "Obrázky"
button: "Tlačidlo"
if: "Ak"
_if:
variable: "Premenné"
post: "Napísať poznámku"
_post:
text: "Obsah"
attachCanvasImage: "Príspevok s obrázkom na plátne"
canvasId: "ID plátna"
textInput: "Textový vstup"
_textInput:
name: "Meno premennej"
text: "Nadpis"
default: "Predvolená hodnota"
textareaInput: "Viacriadkový textový vstup"
_textareaInput:
name: "Meno premennej"
text: "Nadpis"
default: "Predvolená hodnota"
numberInput: "Číselný vstup"
_numberInput:
name: "Meno premennej"
text: "Nadpis"
default: "Predvolená hodnota"
canvas: "Plátno"
_canvas:
id: "ID plátna"
width: "Šírka"
height: "Výška"
note: "Vložená poznámka"
_note:
id: "ID poznámky"
idDescription: "Alebo môžete vložiť URL poznámky sem"
detailed: "Podrobný pohľad"
switch: "Prepnúť"
_switch:
name: "Meno premennej"
text: "Nadpis"
default: "Predvolená hodnota"
counter: "Počítadlo"
_counter:
name: "Meno premennej"
text: "Nadpis"
inc: "Pripočítať"
_button:
text: "Nadpis"
colored: "Farebné"
action: "Operácia po stlačení tlačidla"
_action:
dialog: "Zobraziť dialóg"
_dialog:
content: "Obsah"
resetRandom: "Resetovať zdroj náhodnosti"
pushEvent: "Poslať udalosť"
_pushEvent:
event: "Názov udalosti"
message: "Zobrazená správa po aktivácii"
variable: "Odoslaná premenná"
no-variable: "Žiadne"
callAiScript: "Spustiť AiScript"
_callAiScript:
functionName: "Názov funkcie"
radioButton: "Možnosť"
_radioButton:
name: "Meno premennej"
title: "Nadpis"
values: "Zoznam možností oddelené novými riadkami"
default: "Predvolená hodnota"
script:
categories:
flow: "Riadenie behu"
logical: "Logická operácia"
operation: "Výpočet"
comparison: "Porovnanie"
random: "Náhodné"
value: "Hodnoty"
fn: "Funkcie"
text: "Textové operácie"
convert: "Transformácie"
list: "Zoznamy"
blocks:
text: "Text"
multiLineText: "Text (viacriadkový)"
textList: "Zoznam textov"
_textList:
info: "Oddeľte každú položku novým riadkom"
strLen: "Dĺžka textu"
_strLen:
arg1: "Text"
strPick: "Vybrať znak"
_strPick:
arg1: "Text"
arg2: "Pozícia znaku"
strReplace: "Náhradný text"
_strReplace:
arg1: "Text"
arg2: "Nahradený text"
arg3: "Nahradiť s"
strReverse: "Otočiť text"
_strReverse:
arg1: "Text"
join: "Spojiť texty"
_join:
arg1: "Zoznamy"
arg2: "Oddeľovač"
add: "Pridať"
_add:
arg1: "A"
arg2: "B"
subtract: "Odčítať"
_subtract:
arg1: "A"
arg2: "B"
multiply: "Násobiť"
_multiply:
arg1: "A"
arg2: "B"
divide: "Deliť"
_divide:
arg1: "A"
arg2: "B"
mod: "Zvyšok po delení"
_mod:
arg1: "A"
arg2: "B"
round: "Zaokrúhliť"
_round:
arg1: "Číslo"
eq: "A a B sa rovnajú"
_eq:
arg1: "A"
arg2: "B"
notEq: "A a B sa nerovnajú"
_notEq:
arg1: "A"
arg2: "B"
and: "A a zároveň B"
_and:
arg1: "A"
arg2: "B"
or: "A alebo B"
_or:
arg1: "A"
arg2: "B"
lt: "< A je menšie ako B"
_lt:
arg1: "A"
arg2: "B"
gt: "> A je väčšie ako B"
_gt:
arg1: "A"
arg2: "B"
ltEq: "<= A je menšie alebo rovné B"
_ltEq:
arg1: "A"
arg2: "B"
gtEq: ">= A je väčšie alebo rovné B"
_gtEq:
arg1: "A"
arg2: "B"
if: "Vetva"
_if:
arg1: "Ak"
arg2: "Potom"
arg3: "Inak"
not: "Opak"
_not:
arg1: "Opak"
random: "Náhodné"
_random:
arg1: "Pravdepodobnosť"
rannum: "Náhodné číslo"
_rannum:
arg1: "Minimálna hodnota"
arg2: "Maximálna hodnota"
randomPick: "Náhodný výber zo zoznamu"
_randomPick:
arg1: "Zoznam"
dailyRandom: "Náhodne (zmení sa raz denne pre každého používateľa)"
_dailyRandom:
arg1: "Pravdepodobnosť"
dailyRannum: "Náhodné číslo (Mení sa denne pre každého používateľa)"
_dailyRannum:
arg1: "Minimálna hodnota"
arg2: "Maximálna hodnota"
dailyRandomPick: "Náhodný výber zo zoznamu (Mení sa denne pre každého používateľa)"
_dailyRandomPick:
arg1: "Zoznam"
seedRandom: "Náhodne (so seedom)"
_seedRandom:
arg1: "Seed"
arg2: "Pravdepodobnosť"
seedRannum: "Náhodné číslo (so seedom)"
_seedRannum:
arg1: "Seed"
arg2: "Minimálna hodnota"
arg3: "Maximálna hodnota"
seedRandomPick: "Náhodný výber zo zoznamu (so seedom)"
_seedRandomPick:
arg1: "Seed"
arg2: "Zoznam"
DRPWPM: "Náhodný výber z váženého zoznamu (Mení sa denne pre každého používateľa)"
_DRPWPM:
arg1: "Zoznam textov"
pick: "Vybrať zo zoznamu"
_pick:
arg1: "Zoznam"
arg2: "Pozícia"
listLen: "Získať dĺžku zoznamu"
_listLen:
arg1: "Zoznam"
number: "Číslo"
stringToNumber: "Text na číslo"
_stringToNumber:
arg1: "Text"
numberToString: "Číslo na text"
_numberToString:
arg1: "Číslo"
splitStrByLine: "Rozdelí text po riadkoch"
_splitStrByLine:
arg1: "Text"
ref: "Premenné"
aiScriptVar: "AiScript premenná"
fn: "Funkcie"
_fn:
slots: "Sloty"
slots-info: "Oddeľte každý slot novým riadkom"
arg1: "Výstup"
for: "For cyklus"
_for:
arg1: "Počet opakovaní"
arg2: "Akcia"
typeError: "Slot {slot} akceptuje hodnoty typu \"{expect}\", ale dodaná hodnota je typu \"{actual}\"!"
thereIsEmptySlot: "Slot {slot} je prázdny!"
types:
string: "Text"
number: "Číslo"
boolean: "Boolean"
array: "Zoznamy"
stringArray: "Zoznam textov"
emptySlot: "Prázdny slot"
enviromentVariables: "Premenné prostredia"
pageVariables: "Premenné stránky"
argVariables: "Vstupné sloty"
_relayStatus:
requesting: "Čaká sa"
accepted: "Akceptované"

View File

@ -280,25 +280,6 @@ _exportOrImport:
userLists: "Listor"
_charts:
federation: "Federation"
_pages:
script:
categories:
list: "Listor"
blocks:
_join:
arg1: "Listor"
_randomPick:
arg1: "Listor"
_dailyRandomPick:
arg1: "Listor"
_seedRandomPick:
arg2: "Listor"
_pick:
arg1: "Listor"
_listLen:
arg1: "Listor"
types:
array: "Listor"
_notification:
youWereFollowed: "följde dig"
_types:

View File

@ -1128,10 +1128,7 @@ _pages:
my: "Мої сторінки"
liked: "Вподобані сторінки"
featured: "Популярні"
inspector: "Інспектор"
contents: "Вміст"
content: "Блок сторінки"
variables: "Змінні"
title: "Заголовок"
url: "URL сторінки"
summary: "Короткий зміст"
@ -1142,261 +1139,6 @@ _pages:
fontSansSerif: "Sans serif"
eyeCatchingImageSet: "Встановити привабливе зображення"
eyeCatchingImageRemove: "Видалити привабливе зображення"
chooseBlock: "Додати блок"
selectType: "Виберіть тип"
enterVariableName: "Введіть назву для змінної"
variableNameIsAlreadyUsed: "Ця назва вже використовується іншою змінною"
contentBlocks: "Контент"
inputBlocks: "Ввід"
specialBlocks: "Особливе"
blocks:
text: "Текст"
textarea: "Текстова область"
section: "Розділ"
image: "Зображення"
button: "Кнопка"
if: "Якщо"
_if:
variable: "Змінні"
post: "Створення нотатки"
_post:
text: "Вміст"
canvasId: "Ідентифікатор полотна"
textInput: "Введення тексту"
_textInput:
name: "Ім'я змінної"
text: "Назва"
default: "Значення за замовчуванням"
textareaInput: "Багаторядкове введення тексту"
_textareaInput:
name: "Ім'я змінної"
text: "Назва"
default: "Значення за замовчуванням"
numberInput: "Числове введення"
_numberInput:
name: "Ім'я змінної"
text: "Назва"
default: "Значення за замовчуванням"
canvas: "Полотно"
_canvas:
id: "Ідентифікатор полотна"
width: "Ширина"
height: "Висота"
note: "Вбудована нотатка"
_note:
id: "Ідентифікатор нотатки"
idDescription: "Також можна вказати посилання на нотатку"
detailed: "Детальний вигляд"
switch: "Перемикач"
_switch:
name: "Ім'я змінної"
text: "Назва"
default: "Значення за замовчуванням"
counter: "Лічильник"
_counter:
name: "Ім'я змінної"
text: "Назва"
inc: "Збільшити на"
_button:
text: "Напис"
colored: "Кольоровий"
action: "Дія кнопки"
_action:
dialog: "Показати повідомлення"
_dialog:
content: "Вміст"
resetRandom: "Скидання генератора випадковості"
pushEvent: "Надіслати подію"
_pushEvent:
event: "Назві події"
message: "Повідомлення для відображення при активації"
variable: "Змінна для надсилання"
no-variable: "Відсутньо"
callAiScript: "Виклик AiScript"
_callAiScript:
functionName: "Ім'я функції"
radioButton: "Вибір"
_radioButton:
name: "Ім'я змінної"
title: "Напис"
values: "Варіанти, розділені розривами рядків"
default: "Значення за замовчуванням"
script:
categories:
flow: "Керування потоком"
logical: "Логічні операції"
operation: "Обчислення"
comparison: "Порівняння"
random: "Випадковість"
value: "Значення"
fn: "Функції"
text: "Дії з текстом"
convert: "Перетворення"
list: "Списки"
blocks:
text: "Текст"
multiLineText: "Текст (багаторядковий)"
textList: "Текстовий список"
_textList:
info: "Використовувати новий рядок як роздільник для вводу"
strLen: "Довжина тексту"
_strLen:
arg1: "Текст"
strPick: "Вибрати символ"
_strPick:
arg1: "Текст"
arg2: "Розташування символу"
strReplace: "Заміна тексту"
_strReplace:
arg1: "Текст"
arg2: "Текст, який потрібно замінити"
arg3: "Заміняти на"
strReverse: "Перевернути текст"
_strReverse:
arg1: "Текст"
join: "Конкатенація тексту"
_join:
arg1: "Списки"
arg2: "Розділювач"
add: "Додати"
_add:
arg1: "A"
arg2: "B"
subtract: "Відняти"
_subtract:
arg1: "A"
arg2: "B"
multiply: "Помножити"
_multiply:
arg1: "A"
arg2: "B"
divide: "Поділити"
_divide:
arg1: "A"
arg2: "B"
mod: "Остача"
_mod:
arg1: "A"
arg2: "B"
round: "Десяткове округлення"
_round:
arg1: "Число"
eq: "A дорівнює B"
_eq:
arg1: "A"
arg2: "B"
notEq: "A не дорівнює B"
_notEq:
arg1: "A"
arg2: "B"
and: "А І Б"
_and:
arg1: "A"
arg2: "B"
or: "A АБО B"
_or:
arg1: "A"
arg2: "B"
lt: "< A менше, ніж B"
_lt:
arg1: "A"
arg2: "B"
gt: "> A більше, ніж B"
_gt:
arg1: "A"
arg2: "B"
ltEq: "<= A менше або дорівнює B"
_ltEq:
arg1: "A"
arg2: "B"
gtEq: ">= A більше або дорівнює B"
_gtEq:
arg1: "A"
arg2: "B"
if: "Умова"
_if:
arg1: "Якщо"
arg2: "Якщо так"
arg3: "Якщо ні"
not: "НЕ"
_not:
arg1: "НЕ"
random: "Випадково"
_random:
arg1: "Імовірність"
rannum: "Випадкове число"
_rannum:
arg1: "Мінімальне значення"
arg2: "Максимальне значення"
randomPick: "Випадковий вибір зі списку"
_randomPick:
arg1: "Списки"
dailyRandom: "Випадково (триває добу)"
_dailyRandom:
arg1: "Імовірність"
dailyRannum: "Випадкове число (триває добу)"
_dailyRannum:
arg1: "Мінімальне значення"
arg2: "Максимальне значення"
dailyRandomPick: "Випадково вибрати зі списку (триває добу)"
_dailyRandomPick:
arg1: "Списки"
seedRandom: "Випадковість (з насінням)"
_seedRandom:
arg1: "Насіння"
arg2: "Імовірність"
seedRannum: "Випадкове число (з насінням)"
_seedRannum:
arg1: "Насіння"
arg2: "Мінімальне значення"
arg3: "Максимальне значення"
seedRandomPick: "Випадково вибрати зі списку (з насінням)"
_seedRandomPick:
arg1: "Насіння"
arg2: "Списки"
DRPWPM: "Випадково вибрати зі зваженого списку (триває добу)"
_DRPWPM:
arg1: "Текстовий список"
pick: "Вибір зі списку"
_pick:
arg1: "Списки"
arg2: "Позиція"
listLen: "Отримати довжину списку"
_listLen:
arg1: "Списки"
number: "Число"
stringToNumber: "Текст на число"
_stringToNumber:
arg1: "Текст"
numberToString: "Число на текст"
_numberToString:
arg1: "Число"
splitStrByLine: "Розбиття тексту на рядки"
_splitStrByLine:
arg1: "Текст"
ref: "Змінні"
aiScriptVar: "Змінна AiScript"
fn: "Функції"
_fn:
slots: "Паз"
slots-info: "Використовувати нову лінію як роздільник пазів"
arg1: "Вивід"
for: "Повторення"
_for:
arg1: "Кількість повторень"
arg2: "Дія"
typeError: "Паз {slot} приймає \"{expect}\" тип, але надана змінна має тип \"{actual}\"!"
thereIsEmptySlot: "Паз {slot} пустий!"
types:
string: "Текст"
number: "Число"
boolean: "Прапорець"
array: "Списки"
stringArray: "Текстовий список"
emptySlot: "Пустий паз"
enviromentVariables: "Змінні середовища"
pageVariables: "Елемент сторінки"
argVariables: "Стрічка вводу"
_relayStatus:
requesting: "Очікує затвердження"
accepted: "Затверджено"

View File

@ -1325,10 +1325,7 @@ _pages:
my: "Trang của tôi"
liked: "Trang đã thích"
featured: "Nổi tiếng"
inspector: "Thanh tra"
contents: "Nội dung"
content: "Chặn Trang"
variables: "Biến thể"
title: "Tựa đề"
url: "URL Trang"
summary: "Mô tả Trang"
@ -1339,262 +1336,6 @@ _pages:
fontSansSerif: "Sans Serif"
eyeCatchingImageSet: "Đặt ảnh thu nhỏ"
eyeCatchingImageRemove: "Xóa ảnh thu nhỏ"
chooseBlock: "Thêm khối"
selectType: "Chọn kiểu"
enterVariableName: "Nhập tên một biến thể"
variableNameIsAlreadyUsed: "Tên biến thể này đã được sử dụng"
contentBlocks: "Nội dung"
inputBlocks: "Nhập"
specialBlocks: "Đặc biệt"
blocks:
text: "Văn bản"
textarea: "Khu vực văn bản"
section: "Mục "
image: "Hình ảnh"
button: "Nút"
if: "Nếu"
_if:
variable: "Biến thể"
post: "Mẫu đăng"
_post:
text: "Nội dung"
attachCanvasImage: "Đính kèm hình canva"
canvasId: "ID Canva"
textInput: "Văn bản đầu vào"
_textInput:
name: "Tên biến thể"
text: "Tựa đề"
default: "Giá trị mặc định"
textareaInput: "Văn bản nhiều dòng đầu vào"
_textareaInput:
name: "Tên biến thể"
text: "Tựa đề"
default: "Giá trị mặc định"
numberInput: "Đầu vào số"
_numberInput:
name: "Tên biến thể"
text: "Tựa đề"
default: "Giá trị mặc định"
canvas: "Canva"
_canvas:
id: "ID Canva"
width: "Chiều rộng"
height: "Chiều cao"
note: "Tút đã nhúng"
_note:
id: "ID tút"
idDescription: "Ngoài ra, bạn có thể dán URL tút vào đây."
detailed: "Xem chi tiết"
switch: "Chuyển đổi"
_switch:
name: "Tên biến thể"
text: "Tựa đề"
default: "Giá trị mặc định"
counter: "Bộ đếm"
_counter:
name: "Tên biến thể"
text: "Tựa đề"
inc: "Bước"
_button:
text: "Tựa đề"
colored: "Với màu"
action: "Thao tác khi nhấn nút"
_action:
dialog: "Hiện hộp thoại"
_dialog:
content: "Nội dung"
resetRandom: "Đặt lại seed ngẫu nhiên"
pushEvent: "Gửi một sự kiện"
_pushEvent:
event: "Tên sự kiện"
message: "Tin nhắn hiển thị khi kích hoạt"
variable: "Biển thể để gửi"
no-variable: "Không"
callAiScript: "Gọi AiScript"
_callAiScript:
functionName: "Tên tính năng"
radioButton: "Lựa chọn"
_radioButton:
name: "Tên biến thể"
title: "Tựa đề"
values: "Phân tách các mục bằng cách xuống dòng"
default: "Giá trị mặc định"
script:
categories:
flow: "Điều khiển"
logical: "Hoạt động logic"
operation: "Tính toán"
comparison: "So sánh"
random: "Ngẫu nhiên"
value: "Giá trị"
fn: "Tính năng"
text: "Tác vụ văn bản"
convert: "Chuyển đổi"
list: "Danh sách"
blocks:
text: "Văn bản"
multiLineText: "Văn bản (nhiều dòng)"
textList: "Văn bản liệt kê"
_textList:
info: "Phân tách mục bằng cách xuống dòng"
strLen: "Độ dài văn bản"
_strLen:
arg1: "Văn bản"
strPick: "Trích xuất chuỗi"
_strPick:
arg1: "Văn bản"
arg2: "Vị trí chuỗi"
strReplace: "Thay thế chuỗi"
_strReplace:
arg1: "Nội dung"
arg2: "Văn bản thay thế"
arg3: "Thay thế bằng"
strReverse: "Lật văn bản"
_strReverse:
arg1: "Văn bản"
join: "Nối văn bản"
_join:
arg1: "Danh sách"
arg2: "Phân cách"
add: "Cộng"
_add:
arg1: "A"
arg2: "B"
subtract: "Trừ"
_subtract:
arg1: "A"
arg2: "B"
multiply: "Nhân"
_multiply:
arg1: "A"
arg2: "B"
divide: "Chia"
_divide:
arg1: "A"
arg2: "B"
mod: "Phần còn lại"
_mod:
arg1: "A"
arg2: "B"
round: "Làm tròn thập phân"
_round:
arg1: "Số"
eq: "A và B bằng nhau"
_eq:
arg1: "A"
arg2: "B"
notEq: "A và B khác nhau"
_notEq:
arg1: "A"
arg2: "B"
and: "A VÀ B"
_and:
arg1: "A"
arg2: "B"
or: "A HOẶC B"
_or:
arg1: "A"
arg2: "B"
lt: "< A nhỏ hơn B"
_lt:
arg1: "A"
arg2: "B"
gt: "> A lớn hơn B"
_gt:
arg1: "A"
arg2: "B"
ltEq: "<= A nhỏ hơn hoặc bằng B"
_ltEq:
arg1: "A"
arg2: "B"
gtEq: ">= A lớn hơn hoặc bằng B"
_gtEq:
arg1: "A"
arg2: "B"
if: "Nhánh"
_if:
arg1: "Nếu"
arg2: "Sau đó"
arg3: "Khác"
not: "KHÔNG"
_not:
arg1: "KHÔNG"
random: "Ngẫu nhiên"
_random:
arg1: "Xác suất"
rannum: "Số ngẫu nhiên"
_rannum:
arg1: "Giá trị tối thiểu"
arg2: "Giá trị tối đa"
randomPick: "Chọn ngẫu nhiên từ danh sách"
_randomPick:
arg1: "Danh sách"
dailyRandom: "Ngẫu nhiên (Đổi mỗi người một lần mỗi ngày)"
_dailyRandom:
arg1: "Xác suất"
dailyRannum: "Số ngẫu nhiên (Đổi mỗi người một lần mỗi ngày)"
_dailyRannum:
arg1: "Giá trị tối thiểu"
arg2: "Giá trị tối đa"
dailyRandomPick: "Chọn ngẫu nhiên từ một danh sách (Đổi mỗi người một lần mỗi ngày)"
_dailyRandomPick:
arg1: "Danh sách"
seedRandom: "Ngẫu nhiên (với seed)"
_seedRandom:
arg1: "Seed"
arg2: "Xác suất"
seedRannum: "Số ngẫu nhiên (với seed)"
_seedRannum:
arg1: "Seed"
arg2: "Giá trị tối thiểu"
arg3: "Giá trị tối đa"
seedRandomPick: "Chọn ngẫu nhiên từ danh sách (với seed)"
_seedRandomPick:
arg1: "Seed"
arg2: "Danh sách"
DRPWPM: "Chọn ngẫu nhiên từ danh sách nặng (Đổi mỗi người một lần mỗi ngày)"
_DRPWPM:
arg1: "Văn bản liệt kê"
pick: "Chọn từ danh sách"
_pick:
arg1: "Danh sách"
arg2: "Vị trí"
listLen: "Lấy độ dài danh sách"
_listLen:
arg1: "Danh sách"
number: "Số"
stringToNumber: "Chữ thành số"
_stringToNumber:
arg1: "Văn bản"
numberToString: "Số thành chữ"
_numberToString:
arg1: "Số"
splitStrByLine: "Phân cách văn bản bằng cách xuống dòng"
_splitStrByLine:
arg1: "Văn bản"
ref: "Biến thể"
aiScriptVar: "Biển thể AiScript"
fn: "Tính năng"
_fn:
slots: "Chỗ"
slots-info: "Phân cách chỗ bằng cách xuống dòng"
arg1: "Đầu ra"
for: "để-Lặp lại"
_for:
arg1: "Số lần lặp lại"
arg2: "Hành động"
typeError: "Chỗ {slot} chấp nhận các giá trị thuộc loại \"{expect}\", nhưng giá trị được cung cấp thuộc loại \"{actual}\"!"
thereIsEmptySlot: "Chỗ {slot} đang trống!"
types:
string: "Văn bản"
number: "Số"
boolean: "Cờ"
array: "Danh sách"
stringArray: "Văn bản liệt kê"
emptySlot: "Chỗ trống"
enviromentVariables: "Biến môi trường"
pageVariables: "Biến trang"
argVariables: "Đầu vào chỗ"
_relayStatus:
requesting: "Đang chờ"
accepted: "Đã duyệt"

View File

@ -1324,10 +1324,7 @@ _pages:
my: "我的页面"
liked: "喜欢的页面"
featured: "热门"
inspector: "检查器"
contents: "内容"
content: "页面内容"
variables: "变量"
title: "标题"
url: "页面URL"
summary: "页面摘要"
@ -1338,262 +1335,6 @@ _pages:
fontSansSerif: "无衬线字体"
eyeCatchingImageSet: "设置封面图片"
eyeCatchingImageRemove: "删除封面图片"
chooseBlock: "添加块"
selectType: "选择类型"
enterVariableName: "请输入变量名"
variableNameIsAlreadyUsed: "变量名已使用"
contentBlocks: "内容"
inputBlocks: "输入"
specialBlocks: "特殊"
blocks:
text: "文本"
textarea: "文本区域"
section: "章节"
image: "图片"
button: "按钮"
if: "如果"
_if:
variable: "变量"
post: "投稿窗口"
_post:
text: "内容"
attachCanvasImage: "附加画布图像"
canvasId: "画布ID"
textInput: "文本输入"
_textInput:
name: "变量名"
text: "标题"
default: "默认值"
textareaInput: "多行文本输入"
_textareaInput:
name: "变量名"
text: "标题"
default: "默认值"
numberInput: "输入数值"
_numberInput:
name: "变量名"
text: "标题"
default: "默认值"
canvas: "画布"
_canvas:
id: "画布ID"
width: "宽度"
height: "高度"
note: "嵌入的帖子"
_note:
id: "帖子ID"
idDescription: "您也可以通过粘贴帖子的URL来进行设置。"
detailed: "显示详细信息"
switch: "开关"
_switch:
name: "变量名"
text: "标题"
default: "默认值"
counter: "计数器"
_counter:
name: "变量名"
text: "标题"
inc: "增加值"
_button:
text: "标题"
colored: "彩色"
action: "按下按钮时的行为"
_action:
dialog: "显示对话框"
_dialog:
content: "内容"
resetRandom: "重置随机值"
pushEvent: "发送事件"
_pushEvent:
event: "事件名称"
message: "按下时显示的消息"
variable: "发送的变量"
no-variable: "空"
callAiScript: "调用AiScript"
_callAiScript:
functionName: "函数名"
radioButton: "选择项"
_radioButton:
name: "变量名"
title: "标题"
values: "使用换行区分的选择项"
default: "默认值"
script:
categories:
flow: "控制"
logical: "逻辑运算"
operation: "计算"
comparison: "比较"
random: "随机"
value: "值"
fn: "函数"
text: "文本操作"
convert: "转换"
list: "列表"
blocks:
text: "文本"
multiLineText: "文本 (多行)"
textList: "文本列表"
_textList:
info: "请使用换行符分隔每行"
strLen: "文本长度"
_strLen:
arg1: "文本"
strPick: "提取字符"
_strPick:
arg1: "文本"
arg2: "字符位置"
strReplace: "替换文本"
_strReplace:
arg1: "文本"
arg2: "替换之前"
arg3: "替换之后"
strReverse: "文本反向"
_strReverse:
arg1: "文本"
join: "合并文本"
_join:
arg1: "列表"
arg2: "分隔符"
add: "加"
_add:
arg1: "A"
arg2: "B"
subtract: "减"
_subtract:
arg1: "A"
arg2: "B"
multiply: "乘"
_multiply:
arg1: "A"
arg2: "B"
divide: "除"
_divide:
arg1: "A"
arg2: "B"
mod: "取模(MOD)"
_mod:
arg1: "A"
arg2: "B"
round: "四舍五入"
_round:
arg1: "数值"
eq: "A和B相等"
_eq:
arg1: "A"
arg2: "B"
notEq: "A和B不等"
_notEq:
arg1: "A"
arg2: "B"
and: "A和B"
_and:
arg1: "A"
arg2: "B"
or: "A或B"
_or:
arg1: "A"
arg2: "B"
lt: "< A小于B"
_lt:
arg1: "A"
arg2: "B"
gt: "> A大于B"
_gt:
arg1: "A"
arg2: "B"
ltEq: "<= A小于等于B"
_ltEq:
arg1: "A"
arg2: "B"
gtEq: ">= A大于等于B"
_gtEq:
arg1: "A"
arg2: "B"
if: "分支"
_if:
arg1: "如果"
arg2: "如果"
arg3: "否则"
not: "否"
_not:
arg1: "否"
random: "随机"
_random:
arg1: "概率"
rannum: "随机数"
_rannum:
arg1: "最小值"
arg2: "最大值"
randomPick: "从列表中随机选择"
_randomPick:
arg1: "列表"
dailyRandom: "随机(每个用户每日)"
_dailyRandom:
arg1: "概率"
dailyRannum: "随机数(每个用户每日)"
_dailyRannum:
arg1: "最小值"
arg2: "最大值"
dailyRandomPick: "从列表中随机选择(每个用户每日)"
_dailyRandomPick:
arg1: "列表"
seedRandom: "随机 (种子)"
_seedRandom:
arg1: "种子"
arg2: "概率"
seedRannum: "随机数(种子)"
_seedRannum:
arg1: "种子"
arg2: "最小值"
arg3: "最大值"
seedRandomPick: "从列表中随机选择 (种子)"
_seedRandomPick:
arg1: "种子"
arg2: "列表"
DRPWPM: "从概率列表中随机选择(每用户每天)"
_DRPWPM:
arg1: "文本列表"
pick: "从列表中选择"
_pick:
arg1: "列表"
arg2: "位置"
listLen: "获取列表长度"
_listLen:
arg1: "列表"
number: "数值"
stringToNumber: "文本到数字"
_stringToNumber:
arg1: "文本"
numberToString: "数字到文本"
_numberToString:
arg1: "数值"
splitStrByLine: "将文本按行拆分"
_splitStrByLine:
arg1: "文本"
ref: "变量"
aiScriptVar: "AiScript变量"
fn: "函数"
_fn:
slots: "槽函数"
slots-info: "请使用换行符分隔每个槽函数"
arg1: "输出"
for: "重复"
_for:
arg1: "次数"
arg2: "处理"
typeError: "槽函数{slot}需要传入“{expect}”,但是实际传入为“{actual}”!"
thereIsEmptySlot: "槽函数{slot}为空!"
types:
string: "文字"
number: "数值"
boolean: "Flag"
array: "列表"
stringArray: "文本列表"
emptySlot: "空白槽函数"
enviromentVariables: "环境变量"
pageVariables: "页面元素"
argVariables: "输入变量"
_relayStatus:
requesting: "待批准"
accepted: "已批准"

View File

@ -1324,10 +1324,7 @@ _pages:
my: "我的頁面"
liked: "已喜歡的頁面"
featured: "人氣"
inspector: "面板檢查"
contents: "內容"
content: "頁面方塊"
variables: "變數"
title: "標題"
url: "頁面網址"
summary: "頁面摘要"
@ -1338,262 +1335,6 @@ _pages:
fontSansSerif: "無襯線體"
eyeCatchingImageSet: "設定封面影像"
eyeCatchingImageRemove: "刪除封面影像"
chooseBlock: "新增方塊"
selectType: "選擇類型"
enterVariableName: "請輸入變數名稱"
variableNameIsAlreadyUsed: "變數名稱已被佔用"
contentBlocks: "內容"
inputBlocks: "輸入"
specialBlocks: "特殊"
blocks:
text: "字串"
textarea: "字串區域"
section: "區段"
image: "圖片"
button: "按鈕"
if: "如果"
_if:
variable: "變數"
post: "發佈窗口"
_post:
text: "内容"
attachCanvasImage: "附加相簿圖像 "
canvasId: "畫布ID"
textInput: "插入字串"
_textInput:
name: "變數名稱"
text: "標題"
default: "預設值"
textareaInput: "多行文字输入"
_textareaInput:
name: "變數名稱"
text: "標題"
default: "預設值"
numberInput: "輸入數值"
_numberInput:
name: "變數名稱"
text: "標題"
default: "預設值"
canvas: "畫布"
_canvas:
id: "畫布ID"
width: "寬度"
height: "高度"
note: "嵌式貼文"
_note:
id: "貼文ID"
idDescription: "您也可以粘貼筆記 URL 並進行設置。 "
detailed: "顯示詳細內容"
switch: "開關"
_switch:
name: "變數名稱"
text: "標題"
default: "預設值"
counter: "計數器"
_counter:
name: "變數名稱"
text: "標題"
inc: "増加値"
_button:
text: "標題"
colored: "彩色"
action: "按下按鈕後發生的行為"
_action:
dialog: "顯示對話框 "
_dialog:
content: "内容"
resetRandom: "重設亂數"
pushEvent: "發送事件"
_pushEvent:
event: "事件名稱"
message: "按下時顯示的消息 "
variable: "要發送的變數"
no-variable: "沒有"
callAiScript: "調用AiScript"
_callAiScript:
functionName: "函數名稱"
radioButton: "選項"
_radioButton:
name: "變數名稱"
title: "標題"
values: "由換行符分隔的選項"
default: "預設值"
script:
categories:
flow: "控制"
logical: "邏輯運算"
operation: "計算"
comparison: "對比"
random: "隨機"
value: "數值 "
fn: "函数"
text: "文本操作"
convert: "轉換"
list: "清單"
blocks:
text: "字串"
multiLineText: "字串(多行)"
textList: "字串串列"
_textList:
info: "請分開每個換行符 "
strLen: "字串長度"
_strLen:
arg1: "字串"
strPick: "提取字元"
_strPick:
arg1: "字串"
arg2: "字元位置"
strReplace: "替換字串"
_strReplace:
arg1: "字串"
arg2: "替換前"
arg3: "替換後"
strReverse: "倒轉字串"
_strReverse:
arg1: "字串"
join: "合併字串"
_join:
arg1: "清單"
arg2: "分隔字元"
add: "加"
_add:
arg1: "A"
arg2: "B"
subtract: "减去"
_subtract:
arg1: "A"
arg2: "B"
multiply: "乘"
_multiply:
arg1: "A"
arg2: "B"
divide: "除"
_divide:
arg1: "A"
arg2: "B"
mod: "餘數"
_mod:
arg1: "A"
arg2: "B"
round: "四舍五入"
_round:
arg1: "數值"
eq: "A和B相等"
_eq:
arg1: "A"
arg2: "B"
notEq: "A和B不等"
_notEq:
arg1: "A"
arg2: "B"
and: "A和B"
_and:
arg1: "A"
arg2: "B"
or: "A或B"
_or:
arg1: "A"
arg2: "B"
lt: "< A小於B"
_lt:
arg1: "A"
arg2: "B"
gt: "> A大於B"
_gt:
arg1: "A"
arg2: "B"
ltEq: "<= A小於或等於B"
_ltEq:
arg1: "A"
arg2: "B"
gtEq: ">= A大於或等於B"
_gtEq:
arg1: "A"
arg2: "B"
if: "分支"
_if:
arg1: "如果"
arg2: "如果"
arg3: "除此以外 "
not: "否"
_not:
arg1: "否"
random: "隨機"
_random:
arg1: "機率"
rannum: "亂數"
_rannum:
arg1: "下限"
arg2: "上限"
randomPick: "從列表中隨機選擇 "
_randomPick:
arg1: "清單"
dailyRandom: "隨機(使用者每日變化 )"
_dailyRandom:
arg1: "機率"
dailyRannum: "亂數(使用者每日變化)"
_dailyRannum:
arg1: "下限"
arg2: "上限"
dailyRandomPick: "從列表中隨機選擇(使用者每日變化 "
_dailyRandomPick:
arg1: "清單"
seedRandom: "隨機抽選種子碼"
_seedRandom:
arg1: "種子"
arg2: "機率"
seedRannum: "亂數 (種子)"
_seedRannum:
arg1: "種子"
arg2: "最小值"
arg3: "最大值"
seedRandomPick: "從列表中隨機選擇 (種子)"
_seedRandomPick:
arg1: "種子"
arg2: "清單"
DRPWPM: "从機率列表中隨機選擇(每個用户每天)"
_DRPWPM:
arg1: "字串串列"
pick: "從清單中選取"
_pick:
arg1: "清單"
arg2: "位置"
listLen: "取得清單長度"
_listLen:
arg1: "清單"
number: "數值"
stringToNumber: "將字串轉換至數値"
_stringToNumber:
arg1: "字串"
numberToString: "將數値轉換至字串"
_numberToString:
arg1: "數值"
splitStrByLine: "於換行時分割字串"
_splitStrByLine:
arg1: "字串"
ref: "變數"
aiScriptVar: "AiScript的變數"
fn: "函数"
_fn:
slots: "欄位"
slots-info: "用換行符分隔每個欄位"
arg1: "輸出"
for: "重複 "
_for:
arg1: "重複次數"
arg2: "處理"
typeError: "槽參數{slot}需要傳入“{expect}”,但是實際傳入為“{actual}”!"
thereIsEmptySlot: "參數{slot}是空的!"
types:
string: "字串"
number: "数值"
boolean: "標記"
array: "清單"
stringArray: "字串列表"
emptySlot: "空欄位"
enviromentVariables: "環境變數"
pageVariables: "頁面元素"
argVariables: "輸入欄位"
_relayStatus:
requesting: "等待核准"
accepted: "已通過核准"

View File

@ -0,0 +1,81 @@
export class pagesToPlaintext1659335999000 {
name = 'pagesToPlaintext1659335999000'
async up(queryRunner) {
await queryRunner.query(`ALTER TABLE "page" ADD "text" text`);
async function noteUrl(noteId) {
const note = await queryRunner.query(`SELECT "uri", "userHost" FROM "note" WHERE "id" = $1`, [noteId]);
if (note.uri) return note.uri;
// don't really have access to the configuration here so just guess
else return `https://${note.userHost}/notes/${noteId}`;
}
async function fileUrl(fileId) {
const file = await queryRunner.query(`SELECT "url" from "drive_file" WHERE "id" = $1`, [fileId]);
return file.url;
}
async function convertBlock(block) {
switch (block.type) {
case 'note':
if (block.note) return noteUrl(block.note);
else break;
case 'section':
return block.children.map(convertBlock).join('\n');
case 'text':
return block.text;
case 'textarea':
return '```\n' + block.text + '```';
case 'image':
if (block.fileId) return '![image](' + fileUrl(block.fileId) + ')';
else break;
case 'if': // no idea how to convert these
case 'post': // new note form, why?
case 'canvas': // there is some aiscript api for these but dont think anyone ever used it
// interactive elements can also not be converted
case 'button':
case 'numberInput':
case 'textInput':
case 'switch':
case 'radioButton':
case 'counter':
break;
}
return `(There was a/an ${block.type} here in a previous version but it is no longer supported.)`;
}
await queryRunner.query(`SELECT id, "content" FROM "page"`)
.then(pages => Promise.all(pages.map(page => {
let text = page.content.map(convertBlock).join('\n');
return queryRunner.query(`UPDATE "page" SET "text" = $1 WHERE "id" = $2`, [text, page.id]);
})));
await queryRunner.query(`ALTER TABLE "page" DROP COLUMN "content"`);
await queryRunner.query(`ALTER TABLE "page" DROP COLUMN "variables"`);
await queryRunner.query(`ALTER TABLE "page" DROP COLUMN "script"`);
}
async down(queryRunner) {
await queryRunner.query(`ALTER TABLE "page" ADD "content" jsonb default '[]'::jsonb`);
await queryRunner.query(`ALTER TABLE "page" ADD "variables" jsonb default '[]'::jsonb`);
await queryRunner.query(`ALTER TABLE "page" ADD "script" character varying(16384) default ''`);
// The conversion from the previous page content to text is lossy,
// so we can just convert it back to a big text block.
await queryRunner.query(`SELECT "id", "text" FROM "page"`)
.then(pages => Promise.all(pages.map(page => {
const content = [{
// just a random UUID to keep the data structure
id: '0730b23f-ab5b-4d56-8bd1-f4ead3f72af7',
type: 'text',
text: page.text,
}];
return queryRunner.query(`UPDATE "page" SET "content" = $1 WHERE "id" = $2`, [JSON.stringify(content), page.id]);
})));
await queryRunner.query(`ALTER TABLE "page" DROP COLUMN "text"`);
}
}

View File

@ -75,21 +75,10 @@ export class Page {
@JoinColumn()
public eyeCatchingImage: DriveFile | null;
@Column('jsonb', {
default: [],
})
public content: Record<string, any>[];
@Column('jsonb', {
default: [],
})
public variables: Record<string, any>[];
@Column('varchar', {
length: 16384,
@Column('text', {
default: '',
})
public script: string;
public text: string;
/**
* public ...

View File

@ -2,7 +2,6 @@ import { db } from '@/db/postgre.js';
import { Page } from '@/models/entities/page.js';
import { Packed } from '@/misc/schema.js';
import { awaitAll } from '@/prelude/await-all.js';
import { DriveFile } from '@/models/entities/drive-file.js';
import { User } from '@/models/entities/user.js';
import { Users, DriveFiles, PageLikes } from '../index.js';
@ -14,66 +13,21 @@ export const PageRepository = db.getRepository(Page).extend({
const meId = me ? me.id : null;
const page = typeof src === 'object' ? src : await this.findOneByOrFail({ id: src });
const attachedFiles: Promise<DriveFile | null>[] = [];
const collectFile = (xs: any[]) => {
for (const x of xs) {
if (x.type === 'image') {
attachedFiles.push(DriveFiles.findOneBy({
id: x.fileId,
userId: page.userId,
}));
}
if (x.children) {
collectFile(x.children);
}
}
};
collectFile(page.content);
// 後方互換性のため
let migrated = false;
const migrate = (xs: any[]) => {
for (const x of xs) {
if (x.type === 'input') {
if (x.inputType === 'text') {
x.type = 'textInput';
}
if (x.inputType === 'number') {
x.type = 'numberInput';
if (x.default) x.default = parseInt(x.default, 10);
}
migrated = true;
}
if (x.children) {
migrate(x.children);
}
}
};
migrate(page.content);
if (migrated) {
this.update(page.id, {
content: page.content,
});
}
return await awaitAll({
id: page.id,
createdAt: page.createdAt.toISOString(),
updatedAt: page.updatedAt.toISOString(),
userId: page.userId,
user: Users.pack(page.user || page.userId, me), // { detail: true } すると無限ループするので注意
content: page.content,
variables: page.variables,
text: page.text,
title: page.title,
name: page.name,
summary: page.summary,
hideTitleWhenPinned: page.hideTitleWhenPinned,
alignCenter: page.alignCenter,
font: page.font,
script: page.script,
eyeCatchingImageId: page.eyeCatchingImageId,
eyeCatchingImage: page.eyeCatchingImageId ? await DriveFiles.pack(page.eyeCatchingImageId) : null,
attachedFiles: DriveFiles.packMany((await Promise.all(attachedFiles)).filter((x): x is DriveFile => x != null)),
likedCount: page.likedCount,
isLiked: meId ? await PageLikes.findOneBy({ pageId: page.id, userId: meId }).then(x => x != null) : undefined,
});

View File

@ -29,12 +29,8 @@ export const packedPageSchema = {
type: 'string',
optional: false, nullable: true,
},
content: {
type: 'array',
optional: false, nullable: false,
},
variables: {
type: 'array',
text: {
type: 'string',
optional: false, nullable: false,
},
userId: {

View File

@ -43,19 +43,13 @@ export const paramDef = {
title: { type: 'string' },
name: { type: 'string', minLength: 1 },
summary: { type: 'string', nullable: true },
content: { type: 'array', items: {
type: 'object', additionalProperties: true,
} },
variables: { type: 'array', items: {
type: 'object', additionalProperties: true,
} },
script: { type: 'string' },
text: { type: 'string', minLength: 1 },
eyeCatchingImageId: { type: 'string', format: 'misskey:id', nullable: true },
font: { type: 'string', enum: ['serif', 'sans-serif'], default: 'sans-serif' },
alignCenter: { type: 'boolean', default: false },
hideTitleWhenPinned: { type: 'boolean', default: false },
},
required: ['title', 'name', 'content', 'variables', 'script'],
required: ['title', 'name', 'text'],
} as const;
// eslint-disable-next-line import/no-default-export
@ -88,9 +82,7 @@ export default define(meta, paramDef, async (ps, user) => {
title: ps.title,
name: ps.name,
summary: ps.summary,
content: ps.content,
variables: ps.variables,
script: ps.script,
text: ps.text,
eyeCatchingImageId: eyeCatchingImage ? eyeCatchingImage.id : null,
userId: user.id,
visibility: 'public',

View File

@ -49,19 +49,13 @@ export const paramDef = {
title: { type: 'string' },
name: { type: 'string', minLength: 1 },
summary: { type: 'string', nullable: true },
content: { type: 'array', items: {
type: 'object', additionalProperties: true,
} },
variables: { type: 'array', items: {
type: 'object', additionalProperties: true,
} },
script: { type: 'string' },
text: { type: 'string', minLength: 1 },
eyeCatchingImageId: { type: 'string', format: 'misskey:id', nullable: true },
font: { type: 'string', enum: ['serif', 'sans-serif'] },
alignCenter: { type: 'boolean' },
hideTitleWhenPinned: { type: 'boolean' },
},
required: ['pageId', 'title', 'name', 'content', 'variables', 'script'],
required: ['pageId', 'title', 'name', 'text'],
} as const;
// eslint-disable-next-line import/no-default-export
@ -101,9 +95,7 @@ export default define(meta, paramDef, async (ps, user) => {
title: ps.title,
name: ps.name === undefined ? page.name : ps.name,
summary: ps.name === undefined ? page.summary : ps.summary,
content: ps.content,
variables: ps.variables,
script: ps.script,
text: ps.text,
alignCenter: ps.alignCenter === undefined ? page.alignCenter : ps.alignCenter,
hideTitleWhenPinned: ps.hideTitleWhenPinned === undefined ? page.hideTitleWhenPinned : ps.hideTitleWhenPinned,
font: ps.font === undefined ? page.font : ps.font,

View File

@ -1,44 +0,0 @@
<template>
<component :is="'x-' + block.type" :key="block.id" :block="block" :hpml="hpml" :h="h"/>
</template>
<script lang="ts">
import { defineComponent, PropType } from 'vue';
import XText from './page.text.vue';
import XSection from './page.section.vue';
import XImage from './page.image.vue';
import XButton from './page.button.vue';
import XNumberInput from './page.number-input.vue';
import XTextInput from './page.text-input.vue';
import XTextareaInput from './page.textarea-input.vue';
import XSwitch from './page.switch.vue';
import XIf from './page.if.vue';
import XTextarea from './page.textarea.vue';
import XPost from './page.post.vue';
import XCounter from './page.counter.vue';
import XRadioButton from './page.radio-button.vue';
import XCanvas from './page.canvas.vue';
import XNote from './page.note.vue';
import { Hpml } from '@/scripts/hpml/evaluator';
import { Block } from '@/scripts/hpml/block';
export default defineComponent({
components: {
XText, XSection, XImage, XButton, XNumberInput, XTextInput, XTextareaInput, XTextarea, XPost, XSwitch, XIf, XCounter, XRadioButton, XCanvas, XNote
},
props: {
block: {
type: Object as PropType<Block>,
required: true
},
hpml: {
type: Object as PropType<Hpml>,
required: true
},
h: {
type: Number,
required: true
}
},
});
</script>

View File

@ -1,66 +0,0 @@
<template>
<div>
<MkButton class="kudkigyw" :primary="block.primary" @click="click()">{{ hpml.interpolate(block.text) }}</MkButton>
</div>
</template>
<script lang="ts">
import { defineComponent, PropType, unref } from 'vue';
import MkButton from '../ui/button.vue';
import * as os from '@/os';
import { ButtonBlock } from '@/scripts/hpml/block';
import { Hpml } from '@/scripts/hpml/evaluator';
export default defineComponent({
components: {
MkButton
},
props: {
block: {
type: Object as PropType<ButtonBlock>,
required: true
},
hpml: {
type: Object as PropType<Hpml>,
required: true
}
},
methods: {
click() {
if (this.block.action === 'dialog') {
this.hpml.eval();
os.alert({
text: this.hpml.interpolate(this.block.content)
});
} else if (this.block.action === 'resetRandom') {
this.hpml.updateRandomSeed(Math.random());
this.hpml.eval();
} else if (this.block.action === 'pushEvent') {
os.api('page-push', {
pageId: this.hpml.page.id,
event: this.block.event,
...(this.block.var ? {
var: unref(this.hpml.vars)[this.block.var]
} : {})
});
os.alert({
type: 'success',
text: this.hpml.interpolate(this.block.message)
});
} else if (this.block.action === 'callAiScript') {
this.hpml.callAiScript(this.block.fn);
}
}
}
});
</script>
<style lang="scss" scoped>
.kudkigyw {
display: inline-block;
min-width: 200px;
max-width: 450px;
margin: 8px 0;
}
</style>

View File

@ -1,49 +0,0 @@
<template>
<div class="ysrxegms">
<canvas ref="canvas" :width="block.width" :height="block.height"/>
</div>
</template>
<script lang="ts">
import { defineComponent, onMounted, PropType, Ref, ref } from 'vue';
import * as os from '@/os';
import { CanvasBlock } from '@/scripts/hpml/block';
import { Hpml } from '@/scripts/hpml/evaluator';
export default defineComponent({
props: {
block: {
type: Object as PropType<CanvasBlock>,
required: true
},
hpml: {
type: Object as PropType<Hpml>,
required: true
}
},
setup(props, ctx) {
const canvas: Ref<any> = ref(null);
onMounted(() => {
props.hpml.registerCanvas(props.block.name, canvas.value);
});
return {
canvas
};
}
});
</script>
<style lang="scss" scoped>
.ysrxegms {
display: inline-block;
vertical-align: bottom;
overflow: auto;
max-width: 100%;
> canvas {
display: block;
}
}
</style>

View File

@ -1,52 +0,0 @@
<template>
<div>
<MkButton class="llumlmnx" @click="click()">{{ hpml.interpolate(block.text) }}</MkButton>
</div>
</template>
<script lang="ts">
import { computed, defineComponent, PropType } from 'vue';
import MkButton from '../ui/button.vue';
import * as os from '@/os';
import { CounterVarBlock } from '@/scripts/hpml/block';
import { Hpml } from '@/scripts/hpml/evaluator';
export default defineComponent({
components: {
MkButton
},
props: {
block: {
type: Object as PropType<CounterVarBlock>,
required: true
},
hpml: {
type: Object as PropType<Hpml>,
required: true
}
},
setup(props, ctx) {
const value = computed(() => {
return props.hpml.vars.value[props.block.name];
});
function click() {
props.hpml.updatePageVar(props.block.name, value.value + (props.block.inc || 1));
props.hpml.eval();
}
return {
click
};
}
});
</script>
<style lang="scss" scoped>
.llumlmnx {
display: inline-block;
min-width: 300px;
max-width: 450px;
margin: 8px 0;
}
</style>

View File

@ -1,31 +0,0 @@
<template>
<div v-show="hpml.vars.value[block.var]">
<XBlock v-for="child in block.children" :key="child.id" :block="child" :hpml="hpml" :h="h"/>
</div>
</template>
<script lang="ts">
import { IfBlock } from '@/scripts/hpml/block';
import { Hpml } from '@/scripts/hpml/evaluator';
import { defineComponent, defineAsyncComponent, PropType } from 'vue';
export default defineComponent({
components: {
XBlock: defineAsyncComponent(() => import('./page.block.vue'))
},
props: {
block: {
type: Object as PropType<IfBlock>,
required: true
},
hpml: {
type: Object as PropType<Hpml>,
required: true
},
h: {
type: Number,
required: true
}
},
});
</script>

View File

@ -1,28 +0,0 @@
<template>
<div class="lzyxtsnt">
<ImgWithBlurhash v-if="image" :hash="image.blurhash" :src="image.url" :alt="image.comment" :title="image.comment" :cover="false"/>
</div>
</template>
<script lang="ts" setup>
import { defineComponent, PropType } from 'vue';
import ImgWithBlurhash from '@/components/img-with-blurhash.vue';
import * as os from '@/os';
import { ImageBlock } from '@/scripts/hpml/block';
import { Hpml } from '@/scripts/hpml/evaluator';
const props = defineProps<{
block: PropType<ImageBlock>,
hpml: PropType<Hpml>,
}>();
const image = props.hpml.page.attachedFiles.find(x => x.id === props.block.fileId);
</script>
<style lang="scss" scoped>
.lzyxtsnt {
> img {
max-width: 100%;
}
}
</style>

View File

@ -1,47 +0,0 @@
<template>
<div class="voxdxuby">
<XNote v-if="note && !block.detailed" :key="note.id + ':normal'" v-model:note="note"/>
<XNoteDetailed v-if="note && block.detailed" :key="note.id + ':detail'" v-model:note="note"/>
</div>
</template>
<script lang="ts">
import { defineComponent, onMounted, PropType, Ref, ref } from 'vue';
import XNote from '@/components/note.vue';
import XNoteDetailed from '@/components/note-detailed.vue';
import * as os from '@/os';
import { NoteBlock } from '@/scripts/hpml/block';
export default defineComponent({
components: {
XNote,
XNoteDetailed,
},
props: {
block: {
type: Object as PropType<NoteBlock>,
required: true
}
},
setup(props, ctx) {
const note: Ref<Record<string, any> | null> = ref(null);
onMounted(() => {
os.api('notes/show', { noteId: props.block.note })
.then(result => {
note.value = result;
});
});
return {
note
};
}
});
</script>
<style lang="scss" scoped>
.voxdxuby {
margin: 1em 0;
}
</style>

View File

@ -1,55 +0,0 @@
<template>
<div>
<MkInput class="kudkigyw" :model-value="value" type="number" @update:modelValue="updateValue($event)">
<template #label>{{ hpml.interpolate(block.text) }}</template>
</MkInput>
</div>
</template>
<script lang="ts">
import { computed, defineComponent, PropType } from 'vue';
import MkInput from '../form/input.vue';
import * as os from '@/os';
import { Hpml } from '@/scripts/hpml/evaluator';
import { NumberInputVarBlock } from '@/scripts/hpml/block';
export default defineComponent({
components: {
MkInput
},
props: {
block: {
type: Object as PropType<NumberInputVarBlock>,
required: true
},
hpml: {
type: Object as PropType<Hpml>,
required: true
}
},
setup(props, ctx) {
const value = computed(() => {
return props.hpml.vars.value[props.block.name];
});
function updateValue(newValue) {
props.hpml.updatePageVar(props.block.name, newValue);
props.hpml.eval();
}
return {
value,
updateValue
};
}
});
</script>
<style lang="scss" scoped>
.kudkigyw {
display: inline-block;
min-width: 300px;
max-width: 450px;
margin: 8px 0;
}
</style>

View File

@ -1,111 +0,0 @@
<template>
<div class="ngbfujlo">
<MkTextarea :model-value="text" readonly style="margin: 0;"></MkTextarea>
<MkButton class="button" primary :disabled="posting || posted" @click="post()">
<i v-if="posted" class="fas fa-check"></i>
<i v-else class="fas fa-paper-plane"></i>
</MkButton>
</div>
</template>
<script lang="ts">
import { defineComponent, PropType } from 'vue';
import MkTextarea from '../form/textarea.vue';
import MkButton from '../ui/button.vue';
import { apiUrl } from '@/config';
import * as os from '@/os';
import { PostBlock } from '@/scripts/hpml/block';
import { Hpml } from '@/scripts/hpml/evaluator';
export default defineComponent({
components: {
MkTextarea,
MkButton,
},
props: {
block: {
type: Object as PropType<PostBlock>,
required: true
},
hpml: {
type: Object as PropType<Hpml>,
required: true
}
},
data() {
return {
text: this.hpml.interpolate(this.block.text),
posted: false,
posting: false,
};
},
watch: {
'hpml.vars': {
handler() {
this.text = this.hpml.interpolate(this.block.text);
},
deep: true
}
},
methods: {
upload() {
const promise = new Promise((ok) => {
const canvas = this.hpml.canvases[this.block.canvasId];
canvas.toBlob(blob => {
const formData = new FormData();
formData.append('file', blob);
if (this.$store.state.uploadFolder) {
formData.append('folderId', this.$store.state.uploadFolder);
}
fetch(apiUrl + '/drive/files/create', {
method: 'POST',
body: formData,
headers: {
authorization: `Bearer ${this.$i.token}`,
},
})
.then(response => response.json())
.then(f => {
ok(f);
});
});
});
os.promiseDialog(promise);
return promise;
},
async post() {
this.posting = true;
const file = this.block.attachCanvasImage ? await this.upload() : null;
os.apiWithDialog('notes/create', {
text: this.text === '' ? null : this.text,
fileIds: file ? [file.id] : undefined,
}).then(() => {
this.posted = true;
});
}
}
});
</script>
<style lang="scss" scoped>
.ngbfujlo {
position: relative;
padding: 32px;
border-radius: 6px;
box-shadow: 0 2px 8px var(--shadow);
z-index: 1;
> .button {
margin-top: 32px;
}
@media (max-width: 600px) {
padding: 16px;
> .button {
margin-top: 16px;
}
}
}
</style>

View File

@ -1,45 +0,0 @@
<template>
<div>
<div>{{ hpml.interpolate(block.title) }}</div>
<MkRadio v-for="item in block.values" :key="item" :modelValue="value" :value="item" @update:modelValue="updateValue($event)">{{ item }}</MkRadio>
</div>
</template>
<script lang="ts">
import { computed, defineComponent, PropType } from 'vue';
import MkRadio from '../form/radio.vue';
import * as os from '@/os';
import { Hpml } from '@/scripts/hpml/evaluator';
import { RadioButtonVarBlock } from '@/scripts/hpml/block';
export default defineComponent({
components: {
MkRadio
},
props: {
block: {
type: Object as PropType<RadioButtonVarBlock>,
required: true
},
hpml: {
type: Object as PropType<Hpml>,
required: true
}
},
setup(props, ctx) {
const value = computed(() => {
return props.hpml.vars.value[props.block.name];
});
function updateValue(newValue: string) {
props.hpml.updatePageVar(props.block.name, newValue);
props.hpml.eval();
}
return {
value,
updateValue
};
}
});
</script>

View File

@ -1,60 +0,0 @@
<template>
<section class="sdgxphyu">
<component :is="'h' + h">{{ block.title }}</component>
<div class="children">
<XBlock v-for="child in block.children" :key="child.id" :block="child" :hpml="hpml" :h="h + 1"/>
</div>
</section>
</template>
<script lang="ts">
import { defineComponent, defineAsyncComponent, PropType } from 'vue';
import * as os from '@/os';
import { SectionBlock } from '@/scripts/hpml/block';
import { Hpml } from '@/scripts/hpml/evaluator';
export default defineComponent({
components: {
XBlock: defineAsyncComponent(() => import('./page.block.vue'))
},
props: {
block: {
type: Object as PropType<SectionBlock>,
required: true
},
hpml: {
type: Object as PropType<Hpml>,
required: true
},
h: {
required: true
}
},
});
</script>
<style lang="scss" scoped>
.sdgxphyu {
margin: 1.5em 0;
> h2 {
font-size: 1.35em;
margin: 0 0 0.5em 0;
}
> h3 {
font-size: 1em;
margin: 0 0 0.5em 0;
}
> h4 {
font-size: 1em;
margin: 0 0 0.5em 0;
}
> .children {
//padding 16px
}
}
</style>

View File

@ -1,55 +0,0 @@
<template>
<div class="hkcxmtwj">
<MkSwitch :model-value="value" @update:modelValue="updateValue($event)">{{ hpml.interpolate(block.text) }}</MkSwitch>
</div>
</template>
<script lang="ts">
import { computed, defineComponent, PropType } from 'vue';
import MkSwitch from '../form/switch.vue';
import * as os from '@/os';
import { Hpml } from '@/scripts/hpml/evaluator';
import { SwitchVarBlock } from '@/scripts/hpml/block';
export default defineComponent({
components: {
MkSwitch
},
props: {
block: {
type: Object as PropType<SwitchVarBlock>,
required: true
},
hpml: {
type: Object as PropType<Hpml>,
required: true
}
},
setup(props, ctx) {
const value = computed(() => {
return props.hpml.vars.value[props.block.name];
});
function updateValue(newValue: boolean) {
props.hpml.updatePageVar(props.block.name, newValue);
props.hpml.eval();
}
return {
value,
updateValue
};
}
});
</script>
<style lang="scss" scoped>
.hkcxmtwj {
display: inline-block;
margin: 16px auto;
& + .hkcxmtwj {
margin-left: 16px;
}
}
</style>

View File

@ -1,55 +0,0 @@
<template>
<div>
<MkInput class="kudkigyw" :model-value="value" type="text" @update:modelValue="updateValue($event)">
<template #label>{{ hpml.interpolate(block.text) }}</template>
</MkInput>
</div>
</template>
<script lang="ts">
import { computed, defineComponent, PropType } from 'vue';
import MkInput from '../form/input.vue';
import * as os from '@/os';
import { Hpml } from '@/scripts/hpml/evaluator';
import { TextInputVarBlock } from '@/scripts/hpml/block';
export default defineComponent({
components: {
MkInput
},
props: {
block: {
type: Object as PropType<TextInputVarBlock>,
required: true
},
hpml: {
type: Object as PropType<Hpml>,
required: true
}
},
setup(props, ctx) {
const value = computed(() => {
return props.hpml.vars.value[props.block.name];
});
function updateValue(newValue) {
props.hpml.updatePageVar(props.block.name, newValue);
props.hpml.eval();
}
return {
value,
updateValue
};
}
});
</script>
<style lang="scss" scoped>
.kudkigyw {
display: inline-block;
min-width: 300px;
max-width: 450px;
margin: 8px 0;
}
</style>

View File

@ -1,54 +0,0 @@
<template>
<div class="mrdgzndn">
<Mfm :key="text" :text="text" :is-note="false"/>
<MkUrlPreview v-for="url in urls" :key="url" :url="url" class="url"/>
</div>
</template>
<script lang="ts" setup>
import { defineAsyncComponent, watch, computed } from 'vue';
import * as mfm from 'mfm-js';
import { TextBlock } from '@/scripts/hpml/block';
import { Hpml } from '@/scripts/hpml/evaluator';
import { extractUrlFromMfm } from '@/scripts/extract-url-from-mfm';
const props = defineProps<{
block: TextBlock;
hpml: Hpml;
}>();
const MkUrlPreview = defineAsyncComponent(() => import('@/components/url-preview.vue'));
let text: string = $ref('');
const urls = computed((): string[] => {
if (text) {
return extractUrlFromMfm(mfm.parse(text));
} else {
return [];
}
});
watch(props.hpml.vars, () => {
text = props.hpml.interpolate(props.block.text) as string;
}, {
deep: true,
immediate: true,
});
</script>
<style lang="scss" scoped>
.mrdgzndn {
&:not(:first-child) {
margin-top: 0.5em;
}
&:not(:last-child) {
margin-bottom: 0.5em;
}
> .url {
margin: 0.5em 0;
}
}
</style>

View File

@ -1,47 +0,0 @@
<template>
<div>
<MkTextarea :model-value="value" @update:modelValue="updateValue($event)">
<template #label>{{ hpml.interpolate(block.text) }}</template>
</MkTextarea>
</div>
</template>
<script lang="ts">
import { computed, defineComponent, PropType } from 'vue';
import MkTextarea from '../form/textarea.vue';
import * as os from '@/os';
import { Hpml } from '@/scripts/hpml/evaluator';
import { HpmlTextInput } from '@/scripts/hpml';
import { TextInputVarBlock } from '@/scripts/hpml/block';
export default defineComponent({
components: {
MkTextarea
},
props: {
block: {
type: Object as PropType<TextInputVarBlock>,
required: true
},
hpml: {
type: Object as PropType<Hpml>,
required: true
}
},
setup(props, ctx) {
const value = computed(() => {
return props.hpml.vars.value[props.block.name];
});
function updateValue(newValue) {
props.hpml.updatePageVar(props.block.name, newValue);
props.hpml.eval();
}
return {
value,
updateValue
};
}
});
</script>

View File

@ -1,24 +0,0 @@
<template>
<MkTextarea :model-value="text" readonly></MkTextarea>
</template>
<script lang="ts" setup>
import { watch } from 'vue';
import MkTextarea from '../form/textarea.vue';
import { TextBlock } from '@/scripts/hpml/block';
import { Hpml } from '@/scripts/hpml/evaluator';
const props = defineProps<{
block: TextBlock;
hpml: Hpml;
}>();
let text = $ref('');
watch(props.hpml.vars, () => {
text = props.hpml.interpolate(props.block.text) as string;
}, {
deep: true,
immediate: true,
});
</script>

View File

@ -1,85 +0,0 @@
<template>
<div v-if="hpml" class="iroscrza" :class="{ center: page.alignCenter, serif: page.font === 'serif' }">
<XBlock v-for="child in page.content" :key="child.id" :block="child" :hpml="hpml" :h="2"/>
</div>
</template>
<script lang="ts">
import { defineComponent, onMounted, nextTick, onUnmounted, PropType } from 'vue';
import { parse } from '@syuilo/aiscript';
import XBlock from './page.block.vue';
import { Hpml } from '@/scripts/hpml/evaluator';
import { url } from '@/config';
import { $i } from '@/account';
import { defaultStore } from '@/store';
export default defineComponent({
components: {
XBlock
},
props: {
page: {
type: Object as PropType<Record<string, any>>,
required: true
},
},
setup(props, ctx) {
const hpml = new Hpml(props.page, {
randomSeed: Math.random(),
visitor: $i,
url: url,
enableAiScript: !defaultStore.state.disablePagesScript
});
onMounted(() => {
nextTick(() => {
if (props.page.script && hpml.aiscript) {
let ast;
try {
ast = parse(props.page.script);
} catch (err) {
console.error(err);
/*os.alert({
type: 'error',
text: 'Syntax error :('
});*/
return;
}
hpml.aiscript.exec(ast).then(() => {
hpml.eval();
}).catch(err => {
console.error(err);
/*os.alert({
type: 'error',
text: err
});*/
});
} else {
hpml.eval();
}
});
onUnmounted(() => {
if (hpml.aiscript) hpml.aiscript.abort();
});
});
return {
hpml,
};
},
});
</script>
<style lang="scss" scoped>
.iroscrza {
&.serif {
> div {
font-family: serif;
}
}
&.center {
text-align: center;
}
}
</style>

View File

@ -0,0 +1,265 @@
<template>
<MkStickyContainer>
<template #header><MkPageHeader v-model:tab="tab" :tabs="headerTabs"/></template>
<MkSpacer :content-max="700">
<div class="jqqmcavi">
<MkButton v-if="pageId" class="button" inline link :to="`/@${ author.username }/pages/${ currentName }`"><i class="fas fa-external-link-square-alt"></i> {{ $ts._pages.viewPage }}</MkButton>
<MkButton v-if="!readonly" inline primary class="button" @click="save"><i class="fas fa-save"></i> {{ $ts.save }}</MkButton>
<MkButton v-if="pageId" inline class="button" @click="duplicate"><i class="fas fa-copy"></i> {{ $ts.duplicate }}</MkButton>
<MkButton v-if="pageId && !readonly" inline class="button" danger @click="del"><i class="fas fa-trash-alt"></i> {{ $ts.delete }}</MkButton>
</div>
<div v-if="tab === 'settings'">
<div class="_formRoot">
<MkInput v-model="title" :readonly="readonly" class="_formBlock">
<template #label>{{ $ts._pages.title }}</template>
</MkInput>
<MkInput v-model="summary" :readonly="readonly" class="_formBlock">
<template #label>{{ $ts._pages.summary }}</template>
</MkInput>
<MkInput v-model="name" :readonly="readonly" class="_formBlock">
<template #prefix>{{ url }}/@{{ author.username }}/pages/</template>
<template #label>{{ $ts._pages.url }}</template>
</MkInput>
<MkSwitch v-model="alignCenter" :disabled="readonly" class="_formBlock">{{ $ts._pages.alignCenter }}</MkSwitch>
<MkSelect v-model="font" :readonly="readonly" class="_formBlock">
<template #label>{{ $ts._pages.font }}</template>
<option value="serif">{{ $ts._pages.fontSerif }}</option>
<option value="sans-serif">{{ $ts._pages.fontSansSerif }}</option>
</MkSelect>
<MkSwitch v-model="hideTitleWhenPinned" :disabled="readonly" class="_formBlock">{{ $ts._pages.hideTitleWhenPinned }}</MkSwitch>
<div class="eyeCatch">
<MkButton v-if="eyeCatchingImageId == null && !readonly" @click="setEyeCatchingImage"><i class="fas fa-plus"></i> {{ $ts._pages.eyeCatchingImageSet }}</MkButton>
<div v-else-if="eyeCatchingImage">
<img :src="eyeCatchingImage.url" :alt="eyeCatchingImage.name" style="max-width: 100%;"/>
<MkButton v-if="!readonly" @click="removeEyeCatchingImage()"><i class="fas fa-trash-alt"></i> {{ $ts._pages.eyeCatchingImageRemove }}</MkButton>
</div>
</div>
</div>
</div>
<div v-else-if="tab === 'contents'">
<MkTextarea v-model="text" :readonly="readonly"/>
</div>
</MkSpacer>
</MkStickyContainer>
</template>
<script lang="ts" setup>
import { computed, watch } from 'vue';
import MkButton from '@/components/ui/button.vue';
import MkSelect from '@/components/form/select.vue';
import MkSwitch from '@/components/form/switch.vue';
import MkInput from '@/components/form/input.vue';
import MkTextarea from '@/components/form/textarea.vue';
import { url } from '@/config';
import * as os from '@/os';
import { selectFile } from '@/scripts/select-file';
import { mainRouter } from '@/router';
import { i18n } from '@/i18n';
import { definePageMetadata } from '@/scripts/page-metadata';
import { $i } from '@/account';
const props = defineProps<{
initPageId?: string;
initPageName?: string;
initUser?: string;
}>();
let tab = $ref('settings');
let author = $ref($i);
let readonly = $ref(false);
let page = $ref(null);
let pageId = $ref(null);
let currentName = $ref(null);
let title = $ref('');
let summary = $ref(null);
let text = $ref('Hello, world!');
let name = $ref(Date.now().toString());
let eyeCatchingImage = $ref(null);
let eyeCatchingImageId = $ref(null);
let font = $ref('sans-serif');
let alignCenter = $ref(false);
let hideTitleWhenPinned = $ref(false);
watch($$(eyeCatchingImageId), async () => {
if (eyeCatchingImageId == null) {
eyeCatchingImage = null;
} else {
eyeCatchingImage = await os.api('drive/files/show', {
fileId: eyeCatchingImageId,
});
}
});
function getSaveOptions() {
return {
title: title.trim(),
name: name.trim(),
summary: summary,
font: font,
hideTitleWhenPinned: hideTitleWhenPinned,
alignCenter: alignCenter,
text: text,
eyeCatchingImageId: eyeCatchingImageId,
};
}
function save() {
const options = getSaveOptions();
const onError = err => {
if (err.id === '3d81ceae-475f-4600-b2a8-2bc116157532') {
if (err.info.param === 'name') {
os.alert({
type: 'error',
title: i18n.ts._pages.invalidNameTitle,
text: i18n.ts._pages.invalidNameText,
});
}
} else if (err.code === 'NAME_ALREADY_EXISTS') {
os.alert({
type: 'error',
text: i18n.ts._pages.nameAlreadyExists,
});
}
};
if (pageId) {
options.pageId = pageId;
os.api('pages/update', options)
.then(page => {
currentName = name.trim();
os.alert({
type: 'success',
text: i18n.ts._pages.updated,
});
}).catch(onError);
} else {
os.api('pages/create', options)
.then(created => {
pageId = created.id;
currentName = name.trim();
os.alert({
type: 'success',
text: i18n.ts._pages.created,
});
mainRouter.push(`/pages/edit/${pageId}`);
}).catch(onError);
}
}
function del() {
os.confirm({
type: 'warning',
text: i18n.t('removeAreYouSure', { x: title.trim() }),
}).then(({ canceled }) => {
if (canceled) return;
os.api('pages/delete', {
pageId: pageId,
}).then(() => {
os.alert({
type: 'success',
text: i18n.ts._pages.deleted,
});
mainRouter.push('/pages');
});
});
}
function duplicate() {
title = title + ' - copy';
name = name + '-copy';
os.api('pages/create', getSaveOptions()).then(created => {
pageId = created.id;
currentName = name.trim();
os.alert({
type: 'success',
text: i18n.ts._pages.created,
});
mainRouter.push(`/pages/edit/${pageId}`);
});
}
function setEyeCatchingImage(evt) {
selectFile(evt.currentTarget ?? evt.target, null).then(file => {
eyeCatchingImageId = file.id;
});
}
function removeEyeCatchingImage() {
eyeCatchingImageId = null;
}
async function init() {
if (props.initPageId) {
page = await os.api('pages/show', {
pageId: props.initPageId,
});
} else if (props.initPageName && props.initUser) {
page = await os.api('pages/show', {
name: props.initPageName,
username: props.initUser,
});
readonly = true;
}
if (page) {
author = page.user;
pageId = page.id;
title = page.title;
name = page.name;
currentName = page.name;
summary = page.summary;
font = page.font;
hideTitleWhenPinned = page.hideTitleWhenPinned;
alignCenter = page.alignCenter;
text = page.text;
eyeCatchingImageId = page.eyeCatchingImageId;
}
}
init();
const headerTabs = $computed(() => [{
key: 'settings',
title: i18n.ts._pages.pageSetting,
icon: 'fas fa-cog',
}, {
key: 'contents',
title: i18n.ts._pages.contents,
icon: 'fas fa-sticky-note',
}]);
definePageMetadata(computed(() => {
let title = i18n.ts._pages.newPage;
if (props.initPageId) {
title = i18n.ts._pages.editPage;
}
else if (props.initPageName && props.initUser) {
title = i18n.ts._pages.readPage;
}
return {
title: title,
icon: 'fas fa-pencil-alt',
};
}));
</script>
<style lang="scss" scoped>
.jqqmcavi {
margin-bottom: 1em;
> .button {
& + .button {
margin-left: 8px;
}
}
}
</style>

View File

@ -1,70 +0,0 @@
<template>
<!-- eslint-disable vue/no-mutating-props -->
<XContainer :draggable="true" @remove="() => $emit('remove')">
<template #header><i class="fas fa-bolt"></i> {{ $ts._pages.blocks.button }}</template>
<section class="xfhsjczc">
<MkInput v-model="value.text"><template #label>{{ $ts._pages.blocks._button.text }}</template></MkInput>
<MkSwitch v-model="value.primary"><span>{{ $ts._pages.blocks._button.colored }}</span></MkSwitch>
<MkSelect v-model="value.action">
<template #label>{{ $ts._pages.blocks._button.action }}</template>
<option value="dialog">{{ $ts._pages.blocks._button._action.dialog }}</option>
<option value="resetRandom">{{ $ts._pages.blocks._button._action.resetRandom }}</option>
<option value="pushEvent">{{ $ts._pages.blocks._button._action.pushEvent }}</option>
<option value="callAiScript">{{ $ts._pages.blocks._button._action.callAiScript }}</option>
</MkSelect>
<template v-if="value.action === 'dialog'">
<MkInput v-model="value.content"><template #label>{{ $ts._pages.blocks._button._action._dialog.content }}</template></MkInput>
</template>
<template v-else-if="value.action === 'pushEvent'">
<MkInput v-model="value.event"><template #label>{{ $ts._pages.blocks._button._action._pushEvent.event }}</template></MkInput>
<MkInput v-model="value.message"><template #label>{{ $ts._pages.blocks._button._action._pushEvent.message }}</template></MkInput>
<MkSelect v-model="value.var">
<template #label>{{ $ts._pages.blocks._button._action._pushEvent.variable }}</template>
<option :value="null">{{ $t('_pages.blocks._button._action._pushEvent.no-variable') }}</option>
<option v-for="v in hpml.getVarsByType()" :value="v.name">{{ v.name }}</option>
<optgroup :label="$ts._pages.script.pageVariables">
<option v-for="v in hpml.getPageVarsByType()" :value="v">{{ v }}</option>
</optgroup>
<optgroup :label="$ts._pages.script.enviromentVariables">
<option v-for="v in hpml.getEnvVarsByType()" :value="v">{{ v }}</option>
</optgroup>
</MkSelect>
</template>
<template v-else-if="value.action === 'callAiScript'">
<MkInput v-model="value.fn"><template #label>{{ $ts._pages.blocks._button._action._callAiScript.functionName }}</template></MkInput>
</template>
</section>
</XContainer>
</template>
<script lang="ts" setup>
/* eslint-disable vue/no-mutating-props */
import { } from 'vue';
import XContainer from '../page-editor.container.vue';
import MkSelect from '@/components/form/select.vue';
import MkInput from '@/components/form/input.vue';
import MkSwitch from '@/components/form/switch.vue';
withDefaults(defineProps<{
value: any,
hpml: any
}>(), {
value: {
text: '',
action: 'dialog',
content: null,
event: null,
message: null,
primary: false,
var: null,
fn: null
}
});
</script>
<style lang="scss" scoped>
.xfhsjczc {
padding: 0 16px 0 16px;
}
</style>

View File

@ -1,38 +0,0 @@
<template>
<!-- eslint-disable vue/no-mutating-props -->
<XContainer :draggable="true" @remove="() => $emit('remove')">
<template #header><i class="fas fa-paint-brush"></i> {{ $ts._pages.blocks.canvas }}</template>
<section style="padding: 0 16px 0 16px;">
<MkInput v-model="value.name">
<template #prefix><i class="fas fa-magic"></i></template>
<template #label>{{ $ts._pages.blocks._canvas.id }}</template>
</MkInput>
<MkInput v-model="value.width" type="number">
<template #label>{{ $ts._pages.blocks._canvas.width }}</template>
<template #suffix>px</template>
</MkInput>
<MkInput v-model="value.height" type="number">
<template #label>{{ $ts._pages.blocks._canvas.height }}</template>
<template #suffix>px</template>
</MkInput>
</section>
</XContainer>
</template>
<script lang="ts" setup>
/* eslint-disable vue/no-mutating-props */
import { } from 'vue';
import XContainer from '../page-editor.container.vue';
import MkInput from '@/components/form/input.vue';
withDefaults(defineProps<{
value: any
}>(), {
value: {
name: '',
width: 300,
height: 200
}
});
</script>

View File

@ -1,34 +0,0 @@
<template>
<!-- eslint-disable vue/no-mutating-props -->
<XContainer :draggable="true" @remove="() => $emit('remove')">
<template #header><i class="fas fa-bolt"></i> {{ $ts._pages.blocks.counter }}</template>
<section style="padding: 0 16px 0 16px;">
<MkInput v-model="value.name">
<template #prefix><i class="fas fa-magic"></i></template>
<template #label>{{ $ts._pages.blocks._counter.name }}</template>
</MkInput>
<MkInput v-model="value.text">
<template #label>{{ $ts._pages.blocks._counter.text }}</template>
</MkInput>
<MkInput v-model="value.inc" type="number">
<template #label>{{ $ts._pages.blocks._counter.inc }}</template>
</MkInput>
</section>
</XContainer>
</template>
<script lang="ts" setup>
/* eslint-disable vue/no-mutating-props */
import { } from 'vue';
import XContainer from '../page-editor.container.vue';
import MkInput from '@/components/form/input.vue';
withDefaults(defineProps<{
value: any
}>(), {
value: {
name: ''
}
});
</script>

View File

@ -1,67 +0,0 @@
<template>
<!-- eslint-disable vue/no-mutating-props -->
<XContainer :draggable="true" @remove="() => $emit('remove')">
<template #header><i class="fas fa-question"></i> {{ $ts._pages.blocks.if }}</template>
<template #func>
<button class="_button" @click="add()">
<i class="fas fa-plus"></i>
</button>
</template>
<section class="romcojzs">
<MkSelect v-model="value.var">
<template #label>{{ $ts._pages.blocks._if.variable }}</template>
<option v-for="v in hpml.getVarsByType('boolean')" :value="v.name">{{ v.name }}</option>
<optgroup :label="$ts._pages.script.pageVariables">
<option v-for="v in hpml.getPageVarsByType('boolean')" :value="v">{{ v }}</option>
</optgroup>
<optgroup :label="$ts._pages.script.enviromentVariables">
<option v-for="v in hpml.getEnvVarsByType('boolean')" :value="v">{{ v }}</option>
</optgroup>
</MkSelect>
<XBlocks v-model="value.children" class="children" :hpml="hpml"/>
</section>
</XContainer>
</template>
<script lang="ts" setup>
/* eslint-disable vue/no-mutating-props */
import { defineAsyncComponent, inject } from 'vue';
import { v4 as uuid } from 'uuid';
import XContainer from '../page-editor.container.vue';
import MkSelect from '@/components/form/select.vue';
import * as os from '@/os';
import { i18n } from '@/i18n';
const XBlocks = defineAsyncComponent(() => import('../page-editor.blocks.vue'));
const props = withDefaults(defineProps<{
value: any,
hpml: any
}>(), {
value: {
children: [],
var: null
}
});
const getPageBlockList = inject<(any) => any>('getPageBlockList');
async function add() {
const { canceled, result: type } = await os.select({
title: i18n.ts._pages.chooseBlock,
groupedItems: getPageBlockList()
});
if (canceled) return;
const id = uuid();
props.value.children.push({ id, type });
}
</script>
<style lang="scss" scoped>
.romcojzs {
padding: 0 16px 16px 16px;
}
</style>

View File

@ -1,60 +0,0 @@
<template>
<!-- eslint-disable vue/no-mutating-props -->
<XContainer :draggable="true" @remove="() => $emit('remove')">
<template #header><i class="fas fa-image"></i> {{ $ts._pages.blocks.image }}</template>
<template #func>
<button @click="choose()">
<i class="fas fa-folder-open"></i>
</button>
</template>
<section class="oyyftmcf">
<MkDriveFileThumbnail v-if="file" class="preview" :file="file" fit="contain" @click="choose()"/>
</section>
</XContainer>
</template>
<script lang="ts" setup>
/* eslint-disable vue/no-mutating-props */
import { onMounted } from 'vue';
import XContainer from '../page-editor.container.vue';
import MkDriveFileThumbnail from '@/components/drive-file-thumbnail.vue';
import * as os from '@/os';
const props = withDefaults(defineProps<{
value: any
}>(), {
value: {
fileId: null
}
});
let file: any = $ref(null);
async function choose() {
os.selectDriveFile(false).then((fileResponse: any) => {
file = fileResponse;
props.value.fileId = fileResponse.id;
});
}
onMounted(async () => {
if (props.value.fileId == null) {
await choose();
} else {
os.api('drive/files/show', {
fileId: props.value.fileId
}).then(fileResponse => {
file = fileResponse;
});
}
});
</script>
<style lang="scss" scoped>
.oyyftmcf {
> .preview {
height: 150px;
}
}
</style>

View File

@ -1,52 +0,0 @@
<template>
<!-- eslint-disable vue/no-mutating-props -->
<XContainer :draggable="true" @remove="() => $emit('remove')">
<template #header><i class="fas fa-sticky-note"></i> {{ $ts._pages.blocks.note }}</template>
<section style="padding: 0 16px 0 16px;">
<MkInput v-model="id">
<template #label>{{ $ts._pages.blocks._note.id }}</template>
<template #caption>{{ $ts._pages.blocks._note.idDescription }}</template>
</MkInput>
<MkSwitch v-model="value.detailed"><span>{{ $ts._pages.blocks._note.detailed }}</span></MkSwitch>
<XNote v-if="note && !value.detailed" :key="note.id + ':normal'" v-model:note="note" style="margin-bottom: 16px;"/>
<XNoteDetailed v-if="note && value.detailed" :key="note.id + ':detail'" v-model:note="note" style="margin-bottom: 16px;"/>
</section>
</XContainer>
</template>
<script lang="ts" setup>
/* eslint-disable vue/no-mutating-props */
import { watch } from 'vue';
import XContainer from '../page-editor.container.vue';
import MkInput from '@/components/form/input.vue';
import MkSwitch from '@/components/form/switch.vue';
import XNote from '@/components/note.vue';
import XNoteDetailed from '@/components/note-detailed.vue';
import * as os from '@/os';
const props = withDefaults(defineProps<{
value: any
}>(), {
value: {
note: null,
detailed: false
}
});
let id: any = $ref(props.value.note);
let note: any = $ref(null);
watch(id, async () => {
if (id && (id.startsWith('http://') || id.startsWith('https://'))) {
props.value.note = (id.endsWith('/') ? id.slice(0, -1) : id).split('/').pop();
} else {
props.value.note = id;
}
note = await os.api('notes/show', { noteId: props.value.note });
}, {
immediate: true
});
</script>

View File

@ -1,34 +0,0 @@
<template>
<!-- eslint-disable vue/no-mutating-props -->
<XContainer :draggable="true" @remove="() => $emit('remove')">
<template #header><i class="fas fa-bolt"></i> {{ $ts._pages.blocks.numberInput }}</template>
<section style="padding: 0 16px 0 16px;">
<MkInput v-model="value.name">
<template #prefix><i class="fas fa-magic"></i></template>
<template #label>{{ $ts._pages.blocks._numberInput.name }}</template>
</MkInput>
<MkInput v-model="value.text">
<template #label>{{ $ts._pages.blocks._numberInput.text }}</template>
</MkInput>
<MkInput v-model="value.default" type="number">
<template #label>{{ $ts._pages.blocks._numberInput.default }}</template>
</MkInput>
</section>
</XContainer>
</template>
<script lang="ts" setup>
/* eslint-disable vue/no-mutating-props */
import { } from 'vue';
import XContainer from '../page-editor.container.vue';
import MkInput from '@/components/form/input.vue';
withDefaults(defineProps<{
value: any
}>(), {
value: {
name: ''
}
});
</script>

View File

@ -1,31 +0,0 @@
<template>
<!-- eslint-disable vue/no-mutating-props -->
<XContainer :draggable="true" @remove="() => $emit('remove')">
<template #header><i class="fas fa-paper-plane"></i> {{ $ts._pages.blocks.post }}</template>
<section style="padding: 16px;">
<MkTextarea v-model="value.text"><template #label>{{ $ts._pages.blocks._post.text }}</template></MkTextarea>
<MkSwitch v-model="value.attachCanvasImage"><span>{{ $ts._pages.blocks._post.attachCanvasImage }}</span></MkSwitch>
<MkInput v-if="value.attachCanvasImage" v-model="value.canvasId"><template #label>{{ $ts._pages.blocks._post.canvasId }}</template></MkInput>
</section>
</XContainer>
</template>
<script lang="ts" setup>
/* eslint-disable vue/no-mutating-props */
import { } from 'vue';
import XContainer from '../page-editor.container.vue';
import MkTextarea from '@/components/form/textarea.vue';
import MkInput from '@/components/form/input.vue';
import MkSwitch from '@/components/form/switch.vue';
withDefaults(defineProps<{
value: any
}>(), {
value: {
text: '',
attachCanvasImage: false,
canvasId: ''
}
});
</script>

View File

@ -1,39 +0,0 @@
<template>
<!-- eslint-disable vue/no-mutating-props -->
<XContainer :draggable="true" @remove="() => $emit('remove')">
<template #header><i class="fas fa-bolt"></i> {{ $ts._pages.blocks.radioButton }}</template>
<section style="padding: 0 16px 16px 16px;">
<MkInput v-model="value.name"><template #prefix><i class="fas fa-magic"></i></template><template #label>{{ $ts._pages.blocks._radioButton.name }}</template></MkInput>
<MkInput v-model="value.title"><template #label>{{ $ts._pages.blocks._radioButton.title }}</template></MkInput>
<MkTextarea v-model="values"><template #label>{{ $ts._pages.blocks._radioButton.values }}</template></MkTextarea>
<MkInput v-model="value.default"><template #label>{{ $ts._pages.blocks._radioButton.default }}</template></MkInput>
</section>
</XContainer>
</template>
<script lang="ts" setup>
/* eslint-disable vue/no-mutating-props */
import { watch } from 'vue';
import XContainer from '../page-editor.container.vue';
import MkTextarea from '@/components/form/textarea.vue';
import MkInput from '@/components/form/input.vue';
const props = withDefaults(defineProps<{
value: any
}>(), {
value: {
name: '',
title: '',
values: []
}
});
let values: string = $ref(props.value.values.join('\n'));
watch(values, () => {
props.value.values = values.split('\n');
}, {
deep: true
});
</script>

View File

@ -1,75 +0,0 @@
<template>
<!-- eslint-disable vue/no-mutating-props -->
<XContainer :draggable="true" @remove="() => $emit('remove')">
<template #header><i class="fas fa-sticky-note"></i> {{ value.title }}</template>
<template #func>
<button class="_button" @click="rename()">
<i class="fas fa-pencil-alt"></i>
</button>
<button class="_button" @click="add()">
<i class="fas fa-plus"></i>
</button>
</template>
<section class="ilrvjyvi">
<XBlocks v-model="value.children" class="children" :hpml="hpml"/>
</section>
</XContainer>
</template>
<script lang="ts" setup>
/* eslint-disable vue/no-mutating-props */
import { defineAsyncComponent, inject, onMounted } from 'vue';
import { v4 as uuid } from 'uuid';
import XContainer from '../page-editor.container.vue';
import * as os from '@/os';
import { i18n } from '@/i18n';
const XBlocks = defineAsyncComponent(() => import('../page-editor.blocks.vue'));
const props = withDefaults(defineProps<{
value: any,
hpml: any
}>(), {
value: {
title: null,
children: []
}
});
const getPageBlockList = inject<(any) => any>('getPageBlockList');
async function rename() {
const { canceled, result: title } = await os.inputText({
title: 'Enter title',
default: props.value.title
});
if (canceled) return;
props.value.title = title;
}
async function add() {
const { canceled, result: type } = await os.select({
title: i18n.ts._pages.chooseBlock,
groupedItems: getPageBlockList()
});
if (canceled) return;
const id = uuid();
props.value.children.push({ id, type });
}
onMounted(() => {
if (props.value.title == null) {
rename();
}
});
</script>
<style lang="scss" scoped>
.ilrvjyvi {
> .children {
padding: 16px;
}
}
</style>

View File

@ -1,34 +0,0 @@
<template>
<!-- eslint-disable vue/no-mutating-props -->
<XContainer :draggable="true" @remove="() => $emit('remove')">
<template #header><i class="fas fa-bolt"></i> {{ $ts._pages.blocks.switch }}</template>
<section class="kjuadyyj">
<MkInput v-model="value.name"><template #prefix><i class="fas fa-magic"></i></template><template #label>{{ $ts._pages.blocks._switch.name }}</template></MkInput>
<MkInput v-model="value.text"><template #label>{{ $ts._pages.blocks._switch.text }}</template></MkInput>
<MkSwitch v-model="value.default"><span>{{ $ts._pages.blocks._switch.default }}</span></MkSwitch>
</section>
</XContainer>
</template>
<script lang="ts" setup>
/* eslint-disable vue/no-mutating-props */
import { } from 'vue';
import XContainer from '../page-editor.container.vue';
import MkSwitch from '@/components/form/switch.vue';
import MkInput from '@/components/form/input.vue';
withDefaults(defineProps<{
value: any
}>(), {
value: {
name: ''
}
});
</script>
<style lang="scss" scoped>
.kjuadyyj {
padding: 0 16px 16px 16px;
}
</style>

View File

@ -1,27 +0,0 @@
<template>
<!-- eslint-disable vue/no-mutating-props -->
<XContainer :draggable="true" @remove="() => $emit('remove')">
<template #header><i class="fas fa-bolt"></i> {{ $ts._pages.blocks.textInput }}</template>
<section style="padding: 0 16px 0 16px;">
<MkInput v-model="value.name"><template #prefix><i class="fas fa-magic"></i></template><template #label>{{ $ts._pages.blocks._textInput.name }}</template></MkInput>
<MkInput v-model="value.text"><template #label>{{ $ts._pages.blocks._textInput.text }}</template></MkInput>
<MkInput v-model="value.default" type="text"><template #label>{{ $ts._pages.blocks._textInput.default }}</template></MkInput>
</section>
</XContainer>
</template>
<script lang="ts" setup>
/* eslint-disable vue/no-mutating-props */
import { } from 'vue';
import XContainer from '../page-editor.container.vue';
import MkInput from '@/components/form/input.vue';
withDefaults(defineProps<{
value: any
}>(), {
value: {
name: ''
}
});
</script>

View File

@ -1,45 +0,0 @@
<template>
<!-- eslint-disable vue/no-mutating-props -->
<XContainer :draggable="true" @remove="() => $emit('remove')">
<template #header><i class="fas fa-align-left"></i> {{ $ts._pages.blocks.text }}</template>
<section class="vckmsadr">
<textarea v-model="value.text"></textarea>
</section>
</XContainer>
</template>
<script lang="ts" setup>
/* eslint-disable vue/no-mutating-props */
import { } from 'vue';
import XContainer from '../page-editor.container.vue';
withDefaults(defineProps<{
value: any
}>(), {
value: {
text: ''
}
});
</script>
<style lang="scss" scoped>
.vckmsadr {
> textarea {
display: block;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
width: 100%;
min-width: 100%;
min-height: 150px;
border: none;
box-shadow: none;
padding: 16px;
background: transparent;
color: var(--fg);
font-size: 14px;
box-sizing: border-box;
}
}
</style>

View File

@ -1,28 +0,0 @@
<template>
<!-- eslint-disable vue/no-mutating-props -->
<XContainer :draggable="true" @remove="() => $emit('remove')">
<template #header><i class="fas fa-bolt"></i> {{ $ts._pages.blocks.textareaInput }}</template>
<section style="padding: 0 16px 16px 16px;">
<MkInput v-model="value.name"><template #prefix><i class="fas fa-magic"></i></template><template #label>{{ $ts._pages.blocks._textareaInput.name }}</template></MkInput>
<MkInput v-model="value.text"><template #label>{{ $ts._pages.blocks._textareaInput.text }}</template></MkInput>
<MkTextarea v-model="value.default"><template #label>{{ $ts._pages.blocks._textareaInput.default }}</template></MkTextarea>
</section>
</XContainer>
</template>
<script lang="ts" setup>
/* eslint-disable vue/no-mutating-props */
import { } from 'vue';
import XContainer from '../page-editor.container.vue';
import MkTextarea from '@/components/form/textarea.vue';
import MkInput from '@/components/form/input.vue';
withDefaults(defineProps<{
value: any
}>(), {
value: {
name: ''
}
});
</script>

View File

@ -1,45 +0,0 @@
<template>
<!-- eslint-disable vue/no-mutating-props -->
<XContainer :draggable="true" @remove="() => $emit('remove')">
<template #header><i class="fas fa-align-left"></i> {{ $ts._pages.blocks.textarea }}</template>
<section class="ihymsbbe">
<textarea v-model="value.text"></textarea>
</section>
</XContainer>
</template>
<script lang="ts" setup>
/* eslint-disable vue/no-mutating-props */
import { } from 'vue';
import XContainer from '../page-editor.container.vue';
withDefaults(defineProps<{
value: any
}>(), {
value: {
text: ''
}
});
</script>
<style lang="scss" scoped>
.ihymsbbe {
> textarea {
display: block;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
width: 100%;
min-width: 100%;
min-height: 150px;
border: none;
box-shadow: none;
padding: 16px;
background: transparent;
color: var(--fg);
font-size: 14px;
box-sizing: border-box;
}
}
</style>

View File

@ -1,78 +0,0 @@
<template>
<XDraggable v-model="blocks" tag="div" item-key="id" handle=".drag-handle" :group="{ name: 'blocks' }" animation="150" swap-threshold="0.5">
<template #item="{element}">
<component :is="'x-' + element.type" :value="element" :hpml="hpml" @update:value="updateItem" @remove="() => removeItem(element)"/>
</template>
</XDraggable>
</template>
<script lang="ts">
import { defineComponent, defineAsyncComponent } from 'vue';
import XSection from './els/page-editor.el.section.vue';
import XText from './els/page-editor.el.text.vue';
import XTextarea from './els/page-editor.el.textarea.vue';
import XImage from './els/page-editor.el.image.vue';
import XButton from './els/page-editor.el.button.vue';
import XTextInput from './els/page-editor.el.text-input.vue';
import XTextareaInput from './els/page-editor.el.textarea-input.vue';
import XNumberInput from './els/page-editor.el.number-input.vue';
import XSwitch from './els/page-editor.el.switch.vue';
import XIf from './els/page-editor.el.if.vue';
import XPost from './els/page-editor.el.post.vue';
import XCounter from './els/page-editor.el.counter.vue';
import XRadioButton from './els/page-editor.el.radio-button.vue';
import XCanvas from './els/page-editor.el.canvas.vue';
import XNote from './els/page-editor.el.note.vue';
import * as os from '@/os';
export default defineComponent({
components: {
XDraggable: defineAsyncComponent(() => import('vuedraggable').then(x => x.default)),
XSection, XText, XImage, XButton, XTextarea, XTextInput, XTextareaInput, XNumberInput, XSwitch, XIf, XPost, XCounter, XRadioButton, XCanvas, XNote
},
props: {
modelValue: {
type: Array,
required: true
},
hpml: {
required: true,
},
},
emits: ['update:modelValue'],
computed: {
blocks: {
get() {
return this.modelValue;
},
set(value) {
this.$emit('update:modelValue', value);
}
}
},
methods: {
updateItem(v) {
const i = this.blocks.findIndex(x => x.id === v.id);
const newValue = [
...this.blocks.slice(0, i),
v,
...this.blocks.slice(i + 1)
];
this.$emit('update:modelValue', newValue);
},
removeItem(el) {
const i = this.blocks.findIndex(x => x.id === el.id);
const newValue = [
...this.blocks.slice(0, i),
...this.blocks.slice(i + 1)
];
this.$emit('update:modelValue', newValue);
},
}
});
</script>

View File

@ -1,144 +0,0 @@
<template>
<div class="cpjygsrt" :class="{ error: error != null, warn: warn != null }">
<header>
<div class="title"><slot name="header"></slot></div>
<div class="buttons">
<slot name="func"></slot>
<button v-if="removable" class="_button" @click="emit('remove')">
<i class="fas fa-trash-alt"></i>
</button>
<button v-if="draggable" class="drag-handle _button">
<i class="fas fa-bars"></i>
</button>
<button class="_button" @click="toggleContent(!showBody)">
<template v-if="showBody"><i class="fas fa-angle-up"></i></template>
<template v-else><i class="fas fa-angle-down"></i></template>
</button>
</div>
</header>
<p v-show="showBody" v-if="error != null" class="error">{{ i18n.t('_pages.script.typeError', { slot: error.arg + 1, expect: i18n.t(`script.types.${error.expect}`), actual: i18n.t(`script.types.${error.actual}`) }) }}</p>
<p v-show="showBody" v-if="warn != null" class="warn">{{ i18n.t('_pages.script.thereIsEmptySlot', { slot: warn.slot + 1 }) }}</p>
<div v-show="showBody" class="body">
<slot></slot>
</div>
</div>
</template>
<script lang="ts" setup>
import { } from 'vue';
import { i18n } from '@/i18n';
const emit = defineEmits<{
(ev: 'toggle', v: boolean): void;
(ev: 'remove'): void;
}>();
const props = withDefaults(defineProps<{
expanded?: boolean;
removable?: boolean;
draggable?: boolean;
error?: { arg: number; expect: string; actual: string; };
warn?: { slot: number; };
}>(), {
expanded: true,
removable: true,
draggable: false,
});
let showBody = $ref(props.expanded);
function toggleContent(show: boolean) {
showBody = show;
emit('toggle', show);
}
</script>
<style lang="scss" scoped>
.cpjygsrt {
position: relative;
overflow: hidden;
background: var(--panel);
border: solid 2px var(--X12);
border-radius: 6px;
&:hover {
border: solid 2px var(--X13);
}
&.warn {
border: solid 2px #dec44c;
}
&.error {
border: solid 2px #f00;
}
& + .cpjygsrt {
margin-top: 16px;
}
> header {
> .title {
z-index: 1;
margin: 0;
padding: 0 16px;
line-height: 42px;
font-size: 0.9em;
font-weight: bold;
box-shadow: 0 1px rgba(#000, 0.07);
> i {
margin-right: 6px;
}
&:empty {
display: none;
}
}
> .buttons {
position: absolute;
z-index: 2;
top: 0;
right: 0;
> button {
padding: 0;
width: 42px;
font-size: 0.9em;
line-height: 42px;
}
.drag-handle {
cursor: move;
}
}
}
> .warn {
color: #b19e49;
margin: 0;
padding: 16px 16px 0 16px;
font-size: 14px;
}
> .error {
color: #f00;
margin: 0;
padding: 16px 16px 0 16px;
font-size: 14px;
}
> .body {
::v-deep(.juejbjww), ::v-deep(.eiipwacr) {
&:not(.inline):first-child {
margin-top: 28px;
}
&:not(.inline):last-child {
margin-bottom: 20px;
}
}
}
}
</style>

View File

@ -1,279 +0,0 @@
<template>
<!-- eslint-disable vue/no-mutating-props -->
<XContainer :removable="removable" :error="error" :warn="warn" :draggable="draggable" @remove="() => $emit('remove')">
<template #header><i v-if="icon" :class="icon"></i> <template v-if="title">{{ title }} <span v-if="typeText" class="turmquns">({{ typeText }})</span></template><template v-else-if="typeText">{{ typeText }}</template></template>
<template #func>
<button class="_button" @click="changeType()">
<i class="fas fa-pencil-alt"></i>
</button>
</template>
<section v-if="modelValue.type === null" class="pbglfege" @click="changeType()">
{{ $ts._pages.script.emptySlot }}
</section>
<section v-else-if="modelValue.type === 'text'" class="tbwccoaw">
<input v-model="modelValue.value"/>
</section>
<section v-else-if="modelValue.type === 'multiLineText'" class="tbwccoaw">
<textarea v-model="modelValue.value"></textarea>
</section>
<section v-else-if="modelValue.type === 'textList'" class="tbwccoaw">
<textarea v-model="modelValue.value" :placeholder="$ts._pages.script.blocks._textList.info"></textarea>
</section>
<section v-else-if="modelValue.type === 'number'" class="tbwccoaw">
<input v-model="modelValue.value" type="number"/>
</section>
<section v-else-if="modelValue.type === 'ref'" class="hpdwcrvs">
<select v-model="modelValue.value">
<option v-for="v in hpml.getVarsByType(getExpectedType ? getExpectedType() : null).filter(x => x.name !== name)" :value="v.name">{{ v.name }}</option>
<optgroup :label="$ts._pages.script.argVariables">
<option v-for="v in fnSlots" :value="v.name">{{ v.name }}</option>
</optgroup>
<optgroup :label="$ts._pages.script.pageVariables">
<option v-for="v in hpml.getPageVarsByType(getExpectedType ? getExpectedType() : null)" :value="v">{{ v }}</option>
</optgroup>
<optgroup :label="$ts._pages.script.enviromentVariables">
<option v-for="v in hpml.getEnvVarsByType(getExpectedType ? getExpectedType() : null)" :value="v">{{ v }}</option>
</optgroup>
</select>
</section>
<section v-else-if="modelValue.type === 'aiScriptVar'" class="tbwccoaw">
<input v-model="modelValue.value"/>
</section>
<section v-else-if="modelValue.type === 'fn'" class="" style="padding:0 16px 16px 16px;">
<MkTextarea v-model="slots">
<template #label>{{ $ts._pages.script.blocks._fn.slots }}</template>
<template #caption>{{ $t('_pages.script.blocks._fn.slots-info') }}</template>
</MkTextarea>
<XV v-if="modelValue.value.expression" v-model="modelValue.value.expression" :title="$t(`_pages.script.blocks._fn.arg1`)" :get-expected-type="() => null" :hpml="hpml" :fn-slots="modelValue.value.slots" :name="name"/>
</section>
<section v-else-if="modelValue.type.startsWith('fn:')" class="" style="padding:16px;">
<XV v-for="(x, i) in modelValue.args" :key="i" v-model="modelValue.args[i]" :title="hpml.getVarByName(modelValue.type.split(':')[1]).value.slots[i].name" :get-expected-type="() => null" :hpml="hpml" :name="name"/>
</section>
<section v-else class="" style="padding:16px;">
<XV v-for="(x, i) in modelValue.args" :key="i" v-model="modelValue.args[i]" :title="$t(`_pages.script.blocks._${modelValue.type}.arg${i + 1}`)" :get-expected-type="() => _getExpectedType(i)" :hpml="hpml" :name="name" :fn-slots="fnSlots"/>
</section>
</XContainer>
</template>
<script lang="ts">
/* eslint-disable vue/no-mutating-props */
import { defineAsyncComponent, defineComponent } from 'vue';
import { v4 as uuid } from 'uuid';
import XContainer from './page-editor.container.vue';
import MkTextarea from '@/components/form/textarea.vue';
import { blockDefs } from '@/scripts/hpml/index';
import * as os from '@/os';
import { isLiteralValue } from '@/scripts/hpml/expr';
import { funcDefs } from '@/scripts/hpml/lib';
export default defineComponent({
components: {
XContainer, MkTextarea,
XV: defineAsyncComponent(() => import('./page-editor.script-block.vue')),
},
inject: ['getScriptBlockList'],
props: {
getExpectedType: {
required: false,
default: null
},
modelValue: {
required: true
},
title: {
required: false
},
removable: {
required: false,
default: false
},
hpml: {
required: true,
},
name: {
required: true,
},
fnSlots: {
required: false,
},
draggable: {
required: false,
default: false
}
},
data() {
return {
error: null,
warn: null,
slots: '',
};
},
computed: {
icon(): any {
if (this.modelValue.type === null) return null;
if (this.modelValue.type.startsWith('fn:')) return 'fas fa-plug';
return blockDefs.find(x => x.type === this.modelValue.type).icon;
},
typeText(): any {
if (this.modelValue.type === null) return null;
if (this.modelValue.type.startsWith('fn:')) return this.modelValue.type.split(':')[1];
return this.$t(`_pages.script.blocks.${this.modelValue.type}`);
},
},
watch: {
slots: {
handler() {
this.modelValue.value.slots = this.slots.split('\n').map(x => ({
name: x,
type: null
}));
},
deep: true
}
},
created() {
if (this.modelValue.value == null) this.modelValue.value = null;
if (this.modelValue.value && this.modelValue.value.slots) this.slots = this.modelValue.value.slots.map(x => x.name).join('\n');
this.$watch(() => this.modelValue.type, (t) => {
this.warn = null;
if (this.modelValue.type === 'fn') {
const id = uuid();
this.modelValue.value = {
slots: [],
expression: { id, type: null }
};
return;
}
if (this.modelValue.type && this.modelValue.type.startsWith('fn:')) {
const fnName = this.modelValue.type.split(':')[1];
const fn = this.hpml.getVarByName(fnName);
const empties = [];
for (let i = 0; i < fn.value.slots.length; i++) {
const id = uuid();
empties.push({ id, type: null });
}
this.modelValue.args = empties;
return;
}
if (isLiteralValue(this.modelValue)) return;
const empties = [];
for (let i = 0; i < funcDefs[this.modelValue.type].in.length; i++) {
const id = uuid();
empties.push({ id, type: null });
}
this.modelValue.args = empties;
for (let i = 0; i < funcDefs[this.modelValue.type].in.length; i++) {
const inType = funcDefs[this.modelValue.type].in[i];
if (typeof inType !== 'number') {
if (inType === 'number') this.modelValue.args[i].type = 'number';
if (inType === 'string') this.modelValue.args[i].type = 'text';
}
}
});
this.$watch(() => this.modelValue.args, (args) => {
if (args == null) {
this.warn = null;
return;
}
const emptySlotIndex = args.findIndex(x => x.type === null);
if (emptySlotIndex !== -1 && emptySlotIndex < args.length) {
this.warn = {
slot: emptySlotIndex
};
} else {
this.warn = null;
}
}, {
deep: true
});
this.$watch(() => this.hpml.variables, () => {
if (this.type != null && this.modelValue) {
this.error = this.hpml.typeCheck(this.modelValue);
}
}, {
deep: true
});
},
methods: {
async changeType() {
const { canceled, result: type } = await os.select({
title: this.$ts._pages.selectType,
groupedItems: this.getScriptBlockList(this.getExpectedType ? this.getExpectedType() : null)
});
if (canceled) return;
this.modelValue.type = type;
},
_getExpectedType(slot: number) {
return this.hpml.getExpectedType(this.modelValue, slot);
}
}
});
</script>
<style lang="scss" scoped>
.turmquns {
opacity: 0.7;
}
.pbglfege {
opacity: 0.5;
padding: 16px;
text-align: center;
cursor: pointer;
color: var(--fg);
}
.tbwccoaw {
> input,
> textarea {
display: block;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
width: 100%;
max-width: 100%;
min-width: 100%;
border: none;
box-shadow: none;
padding: 16px;
font-size: 16px;
background: transparent;
color: var(--fg);
box-sizing: border-box;
}
> textarea {
min-height: 100px;
}
}
.hpdwcrvs {
padding: 16px;
> select {
display: block;
padding: 4px;
font-size: 16px;
width: 100%;
}
}
</style>

View File

@ -1,531 +0,0 @@
<template>
<MkStickyContainer>
<template #header><MkPageHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs"/></template>
<MkSpacer :content-max="700">
<div class="jqqmcavi">
<MkButton v-if="pageId" class="button" inline link :to="`/@${ author.username }/pages/${ currentName }`"><i class="fas fa-external-link-square-alt"></i> {{ $ts._pages.viewPage }}</MkButton>
<MkButton v-if="!readonly" inline primary class="button" @click="save"><i class="fas fa-save"></i> {{ $ts.save }}</MkButton>
<MkButton v-if="pageId" inline class="button" @click="duplicate"><i class="fas fa-copy"></i> {{ $ts.duplicate }}</MkButton>
<MkButton v-if="pageId && !readonly" inline class="button" danger @click="del"><i class="fas fa-trash-alt"></i> {{ $ts.delete }}</MkButton>
</div>
<div v-if="tab === 'settings'">
<div class="_formRoot">
<MkInput v-model="title" class="_formBlock">
<template #label>{{ $ts._pages.title }}</template>
</MkInput>
<MkInput v-model="summary" class="_formBlock">
<template #label>{{ $ts._pages.summary }}</template>
</MkInput>
<MkInput v-model="name" class="_formBlock">
<template #prefix>{{ url }}/@{{ author.username }}/pages/</template>
<template #label>{{ $ts._pages.url }}</template>
</MkInput>
<MkSwitch v-model="alignCenter" class="_formBlock">{{ $ts._pages.alignCenter }}</MkSwitch>
<MkSelect v-model="font" class="_formBlock">
<template #label>{{ $ts._pages.font }}</template>
<option value="serif">{{ $ts._pages.fontSerif }}</option>
<option value="sans-serif">{{ $ts._pages.fontSansSerif }}</option>
</MkSelect>
<MkSwitch v-model="hideTitleWhenPinned" class="_formBlock">{{ $ts._pages.hideTitleWhenPinned }}</MkSwitch>
<div class="eyeCatch">
<MkButton v-if="eyeCatchingImageId == null && !readonly" @click="setEyeCatchingImage"><i class="fas fa-plus"></i> {{ $ts._pages.eyeCatchingImageSet }}</MkButton>
<div v-else-if="eyeCatchingImage">
<img :src="eyeCatchingImage.url" :alt="eyeCatchingImage.name" style="max-width: 100%;"/>
<MkButton v-if="!readonly" @click="removeEyeCatchingImage()"><i class="fas fa-trash-alt"></i> {{ $ts._pages.eyeCatchingImageRemove }}</MkButton>
</div>
</div>
</div>
</div>
<div v-else-if="tab === 'contents'">
<div>
<XBlocks v-model="content" class="content" :hpml="hpml"/>
<MkButton v-if="!readonly" @click="add()"><i class="fas fa-plus"></i></MkButton>
</div>
</div>
<div v-else-if="tab === 'variables'">
<div class="qmuvgica">
<XDraggable v-show="variables.length > 0" v-model="variables" tag="div" class="variables" item-key="name" handle=".drag-handle" :group="{ name: 'variables' }" animation="150" swap-threshold="0.5">
<template #item="{element}">
<XVariable
:model-value="element"
:removable="true"
:hpml="hpml"
:name="element.name"
:title="element.name"
:draggable="true"
@remove="() => removeVariable(element)"
/>
</template>
</XDraggable>
<MkButton v-if="!readonly" class="add" @click="addVariable()"><i class="fas fa-plus"></i></MkButton>
</div>
</div>
<div v-else-if="tab === 'script'">
<div>
<MkTextarea v-model="script" class="_code"/>
</div>
</div>
</MkSpacer>
</MkStickyContainer>
</template>
<script lang="ts" setup>
import { defineAsyncComponent, computed, provide, watch } from 'vue';
import 'prismjs';
import { highlight, languages } from 'prismjs/components/prism-core';
import 'prismjs/components/prism-clike';
import 'prismjs/components/prism-javascript';
import 'prismjs/themes/prism-okaidia.css';
import 'vue-prism-editor/dist/prismeditor.min.css';
import { v4 as uuid } from 'uuid';
import XVariable from './page-editor.script-block.vue';
import XBlocks from './page-editor.blocks.vue';
import MkTextarea from '@/components/form/textarea.vue';
import MkButton from '@/components/ui/button.vue';
import MkSelect from '@/components/form/select.vue';
import MkSwitch from '@/components/form/switch.vue';
import MkInput from '@/components/form/input.vue';
import { blockDefs } from '@/scripts/hpml/index';
import { HpmlTypeChecker } from '@/scripts/hpml/type-checker';
import { url } from '@/config';
import { collectPageVars } from '@/scripts/collect-page-vars';
import * as os from '@/os';
import { selectFile } from '@/scripts/select-file';
import { mainRouter } from '@/router';
import { i18n } from '@/i18n';
import { definePageMetadata } from '@/scripts/page-metadata';
import { $i } from '@/account';
const XDraggable = defineAsyncComponent(() => import('vuedraggable').then(x => x.default));
const props = defineProps<{
initPageId?: string;
initPageName?: string;
initUser?: string;
}>();
let tab = $ref('settings');
let author = $ref($i);
let readonly = $ref(false);
let page = $ref(null);
let pageId = $ref(null);
let currentName = $ref(null);
let title = $ref('');
let summary = $ref(null);
let name = $ref(Date.now().toString());
let eyeCatchingImage = $ref(null);
let eyeCatchingImageId = $ref(null);
let font = $ref('sans-serif');
let content = $ref([]);
let alignCenter = $ref(false);
let hideTitleWhenPinned = $ref(false);
let variables = $ref([]);
let hpml = $ref(null);
let script = $ref('');
provide('readonly', readonly);
provide('getScriptBlockList', getScriptBlockList);
provide('getPageBlockList', getPageBlockList);
watch($$(eyeCatchingImageId), async () => {
if (eyeCatchingImageId == null) {
eyeCatchingImage = null;
} else {
eyeCatchingImage = await os.api('drive/files/show', {
fileId: eyeCatchingImageId,
});
}
});
function getSaveOptions() {
return {
title: title.trim(),
name: name.trim(),
summary: summary,
font: font,
script: script,
hideTitleWhenPinned: hideTitleWhenPinned,
alignCenter: alignCenter,
content: content,
variables: variables,
eyeCatchingImageId: eyeCatchingImageId,
};
}
function save() {
const options = getSaveOptions();
const onError = err => {
if (err.id === '3d81ceae-475f-4600-b2a8-2bc116157532') {
if (err.info.param === 'name') {
os.alert({
type: 'error',
title: i18n.ts._pages.invalidNameTitle,
text: i18n.ts._pages.invalidNameText,
});
}
} else if (err.code === 'NAME_ALREADY_EXISTS') {
os.alert({
type: 'error',
text: i18n.ts._pages.nameAlreadyExists,
});
}
};
if (pageId) {
options.pageId = pageId;
os.api('pages/update', options)
.then(page => {
currentName = name.trim();
os.alert({
type: 'success',
text: i18n.ts._pages.updated,
});
}).catch(onError);
} else {
os.api('pages/create', options)
.then(created => {
pageId = created.id;
currentName = name.trim();
os.alert({
type: 'success',
text: i18n.ts._pages.created,
});
mainRouter.push(`/pages/edit/${pageId}`);
}).catch(onError);
}
}
function del() {
os.confirm({
type: 'warning',
text: i18n.t('removeAreYouSure', { x: title.trim() }),
}).then(({ canceled }) => {
if (canceled) return;
os.api('pages/delete', {
pageId: pageId,
}).then(() => {
os.alert({
type: 'success',
text: i18n.ts._pages.deleted,
});
mainRouter.push('/pages');
});
});
}
function duplicate() {
title = title + ' - copy';
name = name + '-copy';
os.api('pages/create', getSaveOptions()).then(created => {
pageId = created.id;
currentName = name.trim();
os.alert({
type: 'success',
text: i18n.ts._pages.created,
});
mainRouter.push(`/pages/edit/${pageId}`);
});
}
async function add() {
const { canceled, result: type } = await os.select({
type: null,
title: i18n.ts._pages.chooseBlock,
groupedItems: getPageBlockList(),
});
if (canceled) return;
const id = uuid();
content.push({ id, type });
}
async function addVariable() {
let { canceled, result: name } = await os.inputText({
title: i18n.ts._pages.enterVariableName,
});
if (canceled) return;
name = name.trim();
if (hpml.isUsedName(name)) {
os.alert({
type: 'error',
text: i18n.ts._pages.variableNameIsAlreadyUsed,
});
return;
}
const id = uuid();
variables.push({ id, name, type: null });
}
function removeVariable(v) {
variables = variables.filter(x => x.name !== v.name);
}
function getPageBlockList() {
return [{
label: i18n.ts._pages.contentBlocks,
items: [
{ value: 'section', text: i18n.ts._pages.blocks.section },
{ value: 'text', text: i18n.ts._pages.blocks.text },
{ value: 'image', text: i18n.ts._pages.blocks.image },
{ value: 'textarea', text: i18n.ts._pages.blocks.textarea },
{ value: 'note', text: i18n.ts._pages.blocks.note },
{ value: 'canvas', text: i18n.ts._pages.blocks.canvas },
],
}, {
label: i18n.ts._pages.inputBlocks,
items: [
{ value: 'button', text: i18n.ts._pages.blocks.button },
{ value: 'radioButton', text: i18n.ts._pages.blocks.radioButton },
{ value: 'textInput', text: i18n.ts._pages.blocks.textInput },
{ value: 'textareaInput', text: i18n.ts._pages.blocks.textareaInput },
{ value: 'numberInput', text: i18n.ts._pages.blocks.numberInput },
{ value: 'switch', text: i18n.ts._pages.blocks.switch },
{ value: 'counter', text: i18n.ts._pages.blocks.counter },
],
}, {
label: i18n.ts._pages.specialBlocks,
items: [
{ value: 'if', text: i18n.ts._pages.blocks.if },
{ value: 'post', text: i18n.ts._pages.blocks.post },
],
}];
}
function getScriptBlockList(type: string = null) {
const list = [];
const blocks = blockDefs.filter(block => type == null || block.out == null || block.out === type || typeof block.out === 'number');
for (const block of blocks) {
const category = list.find(x => x.category === block.category);
if (category) {
category.items.push({
value: block.type,
text: i18n.t(`_pages.script.blocks.${block.type}`),
});
} else {
list.push({
category: block.category,
label: i18n.t(`_pages.script.categories.${block.category}`),
items: [{
value: block.type,
text: i18n.t(`_pages.script.blocks.${block.type}`),
}],
});
}
}
const userFns = variables.filter(x => x.type === 'fn');
if (userFns.length > 0) {
list.unshift({
label: i18n.t('_pages.script.categories.fn'),
items: userFns.map(v => ({
value: 'fn:' + v.name,
text: v.name,
})),
});
}
return list;
}
function setEyeCatchingImage(evt) {
selectFile(evt.currentTarget ?? evt.target, null).then(file => {
eyeCatchingImageId = file.id;
});
}
function removeEyeCatchingImage() {
eyeCatchingImageId = null;
}
function highlighter(code) {
return highlight(code, languages.js, 'javascript');
}
async function init() {
hpml = new HpmlTypeChecker();
watch($$(variables), () => {
hpml.variables = variables;
}, { deep: true });
watch($$(content), () => {
hpml.pageVars = collectPageVars(content);
}, { deep: true });
if (props.initPageId) {
page = await os.api('pages/show', {
pageId: props.initPageId,
});
} else if (props.initPageName && props.initUser) {
page = await os.api('pages/show', {
name: props.initPageName,
username: props.initUser,
});
readonly = true;
}
if (page) {
author = page.user;
pageId = page.id;
title = page.title;
name = page.name;
currentName = page.name;
summary = page.summary;
font = page.font;
script = page.script;
hideTitleWhenPinned = page.hideTitleWhenPinned;
alignCenter = page.alignCenter;
content = page.content;
variables = page.variables;
eyeCatchingImageId = page.eyeCatchingImageId;
} else {
const id = uuid();
content = [{
id,
type: 'text',
text: 'Hello World!',
}];
}
}
init();
const headerActions = $computed(() => []);
const headerTabs = $computed(() => [{
key: 'settings',
title: i18n.ts._pages.pageSetting,
icon: 'fas fa-cog',
}, {
key: 'contents',
title: i18n.ts._pages.contents,
icon: 'fas fa-sticky-note',
}, {
key: 'variables',
title: i18n.ts._pages.variables,
icon: 'fas fa-magic',
}, {
key: 'script',
title: i18n.ts.script,
icon: 'fas fa-code',
}]);
definePageMetadata(computed(() => {
let title = i18n.ts._pages.newPage;
if (props.initPageId) {
title = i18n.ts._pages.editPage;
}
else if (props.initPageName && props.initUser) {
title = i18n.ts._pages.readPage;
}
return {
title: title,
icon: 'fas fa-pencil-alt',
};
}));
</script>
<style lang="scss" scoped>
.jqqmcavi {
> .button {
& + .button {
margin-left: 8px;
}
}
}
.gwbmwxkm {
position: relative;
> header {
> .title {
z-index: 1;
margin: 0;
padding: 0 16px;
line-height: 42px;
font-size: 0.9em;
font-weight: bold;
box-shadow: 0 1px rgba(#000, 0.07);
> i {
margin-right: 6px;
}
&:empty {
display: none;
}
}
> .buttons {
position: absolute;
z-index: 2;
top: 0;
right: 0;
> button {
padding: 0;
width: 42px;
font-size: 0.9em;
line-height: 42px;
}
}
}
> section {
padding: 0 32px 32px 32px;
@media (max-width: 500px) {
padding: 0 16px 16px 16px;
}
> .view {
display: inline-block;
margin: 16px 0 0 0;
font-size: 14px;
}
> .content {
margin-bottom: 16px;
}
> .eyeCatch {
margin-bottom: 16px;
> div {
> img {
max-width: 100%;
}
}
}
}
}
.qmuvgica {
padding: 16px;
> .variables {
margin-bottom: 16px;
}
> .add {
margin-bottom: 16px;
}
}
</style>

View File

@ -1,20 +1,15 @@
<template>
<MkStickyContainer>
<template #header><MkPageHeader :actions="headerActions" :tabs="headerTabs"/></template>
<template #header><MkPageHeader/></template>
<MkSpacer :content-max="700">
<transition :name="$store.state.animation ? 'fade' : ''" mode="out-in">
<div v-if="page" :key="page.id" v-size="{ max: [450] }" class="xcukqgmh">
<div class="_block main">
<!--
<div class="header">
<h1>{{ page.title }}</h1>
</div>
-->
<div class="banner">
<img v-if="page.eyeCatchingImageId" :src="page.eyeCatchingImage.url"/>
</div>
<div class="content">
<XPage :page="page"/>
<div class="content" :class="{ center: page.alignCenter, serif: page.font === 'serif' }">
<Mfm :text="page.text" :is-note="false"/>
</div>
<div class="actions">
<div class="like">
@ -63,7 +58,6 @@
<script lang="ts" setup>
import { computed, watch } from 'vue';
import XPage from '@/components/page/page.vue';
import MkButton from '@/components/ui/button.vue';
import * as os from '@/os';
import { url } from '@/config';
@ -196,6 +190,16 @@ definePageMetadata(computed(() => page ? {
> .content {
margin-top: 1em;
padding: 1em;
&.serif {
> div {
font-family: serif;
}
}
&.center {
text-align: center;
}
}
> .actions {

View File

@ -13,7 +13,7 @@ const page = (loader: AsyncComponentLoader<any>) => defineAsyncComponent({
export const routes = [{
path: '/@:initUser/pages/:initPageName/view-source',
component: page(() => import('./pages/page-editor/page-editor.vue')),
component: page(() => import('./pages/page-editor.vue')),
}, {
path: '/@:username/pages/:pageName',
component: page(() => import('./pages/page.vue')),
@ -122,11 +122,11 @@ export const routes = [{
component: page(() => import('./pages/tag.vue')),
}, {
path: '/pages/new',
component: page(() => import('./pages/page-editor/page-editor.vue')),
component: page(() => import('./pages/page-editor.vue')),
loginRequired: true,
}, {
path: '/pages/edit/:initPageId',
component: page(() => import('./pages/page-editor/page-editor.vue')),
component: page(() => import('./pages/page-editor.vue')),
loginRequired: true,
}, {
path: '/pages',

View File

@ -1,48 +0,0 @@
export function collectPageVars(content) {
const pageVars = [];
const collect = (xs: any[]) => {
for (const x of xs) {
if (x.type === 'textInput') {
pageVars.push({
name: x.name,
type: 'string',
value: x.default || ''
});
} else if (x.type === 'textareaInput') {
pageVars.push({
name: x.name,
type: 'string',
value: x.default || ''
});
} else if (x.type === 'numberInput') {
pageVars.push({
name: x.name,
type: 'number',
value: x.default || 0
});
} else if (x.type === 'switch') {
pageVars.push({
name: x.name,
type: 'boolean',
value: x.default || false
});
} else if (x.type === 'counter') {
pageVars.push({
name: x.name,
type: 'number',
value: 0
});
} else if (x.type === 'radioButton') {
pageVars.push({
name: x.name,
type: 'string',
value: x.default || ''
});
} else if (x.children) {
collect(x.children);
}
}
};
collect(content);
return pageVars;
}

View File

@ -1,109 +0,0 @@
// blocks
export type BlockBase = {
id: string;
type: string;
};
export type TextBlock = BlockBase & {
type: 'text';
text: string;
};
export type SectionBlock = BlockBase & {
type: 'section';
title: string;
children: (Block | VarBlock)[];
};
export type ImageBlock = BlockBase & {
type: 'image';
fileId: string | null;
};
export type ButtonBlock = BlockBase & {
type: 'button';
text: any;
primary: boolean;
action: string;
content: string;
event: string;
message: string;
var: string;
fn: string;
};
export type IfBlock = BlockBase & {
type: 'if';
var: string;
children: Block[];
};
export type TextareaBlock = BlockBase & {
type: 'textarea';
text: string;
};
export type PostBlock = BlockBase & {
type: 'post';
text: string;
attachCanvasImage: boolean;
canvasId: string;
};
export type CanvasBlock = BlockBase & {
type: 'canvas';
name: string; // canvas id
width: number;
height: number;
};
export type NoteBlock = BlockBase & {
type: 'note';
detailed: boolean;
note: string | null;
};
export type Block =
TextBlock | SectionBlock | ImageBlock | ButtonBlock | IfBlock | TextareaBlock | PostBlock | CanvasBlock | NoteBlock | VarBlock;
// variable blocks
export type VarBlockBase = BlockBase & {
name: string;
};
export type NumberInputVarBlock = VarBlockBase & {
type: 'numberInput';
text: string;
};
export type TextInputVarBlock = VarBlockBase & {
type: 'textInput';
text: string;
};
export type SwitchVarBlock = VarBlockBase & {
type: 'switch';
text: string;
};
export type RadioButtonVarBlock = VarBlockBase & {
type: 'radioButton';
title: string;
values: string[];
};
export type CounterVarBlock = VarBlockBase & {
type: 'counter';
text: string;
inc: number;
};
export type VarBlock =
NumberInputVarBlock | TextInputVarBlock | SwitchVarBlock | RadioButtonVarBlock | CounterVarBlock;
const varBlock = ['numberInput', 'textInput', 'switch', 'radioButton', 'counter'];
export function isVarBlock(block: Block): block is VarBlock {
return varBlock.includes(block.type);
}

View File

@ -1,232 +0,0 @@
import autobind from 'autobind-decorator';
import { PageVar, envVarsDef, Fn, HpmlScope, HpmlError } from '.';
import { version } from '@/config';
import { AiScript, utils, values } from '@syuilo/aiscript';
import { createAiScriptEnv } from '../aiscript/api';
import { collectPageVars } from '../collect-page-vars';
import { initHpmlLib, initAiLib } from './lib';
import * as os from '@/os';
import { markRaw, ref, Ref, unref } from 'vue';
import { Expr, isLiteralValue, Variable } from './expr';
/**
* Hpml evaluator
*/
export class Hpml {
private variables: Variable[];
private pageVars: PageVar[];
private envVars: Record<keyof typeof envVarsDef, any>;
public aiscript?: AiScript;
public pageVarUpdatedCallback?: values.VFn;
public canvases: Record<string, HTMLCanvasElement> = {};
public vars: Ref<Record<string, any>> = ref({});
public page: Record<string, any>;
private opts: {
randomSeed: string; visitor?: any; url?: string;
enableAiScript: boolean;
};
constructor(page: Hpml['page'], opts: Hpml['opts']) {
this.page = page;
this.variables = this.page.variables;
this.pageVars = collectPageVars(this.page.content);
this.opts = opts;
if (this.opts.enableAiScript) {
this.aiscript = markRaw(new AiScript({ ...createAiScriptEnv({
storageKey: 'pages:' + this.page.id
}), ...initAiLib(this) }, {
in: (q) => {
return new Promise(ok => {
os.inputText({
title: q,
}).then(({ canceled, result: a }) => {
ok(a);
});
});
},
out: (value) => {
console.log(value);
},
log: (type, params) => {
},
}));
this.aiscript.scope.opts.onUpdated = (name, value) => {
this.eval();
};
}
const date = new Date();
this.envVars = {
AI: 'kawaii',
VERSION: version,
URL: this.page ? `${opts.url}/@${this.page.user.username}/pages/${this.page.name}` : '',
LOGIN: opts.visitor != null,
NAME: opts.visitor ? opts.visitor.name || opts.visitor.username : '',
USERNAME: opts.visitor ? opts.visitor.username : '',
USERID: opts.visitor ? opts.visitor.id : '',
NOTES_COUNT: opts.visitor ? opts.visitor.notesCount : 0,
FOLLOWERS_COUNT: opts.visitor ? opts.visitor.followersCount : 0,
FOLLOWING_COUNT: opts.visitor ? opts.visitor.followingCount : 0,
IS_CAT: opts.visitor ? opts.visitor.isCat : false,
SEED: opts.randomSeed ? opts.randomSeed : '',
YMD: `${date.getFullYear()}/${date.getMonth() + 1}/${date.getDate()}`,
AISCRIPT_DISABLED: !this.opts.enableAiScript,
NULL: null
};
this.eval();
}
@autobind
public eval() {
try {
this.vars.value = this.evaluateVars();
} catch (err) {
//this.onError(e);
}
}
@autobind
public interpolate(str: string) {
if (str == null) return null;
return str.replace(/{(.+?)}/g, match => {
const v = unref(this.vars)[match.slice(1, -1).trim()];
return v == null ? 'NULL' : v.toString();
});
}
@autobind
public callAiScript(fn: string) {
try {
if (this.aiscript) this.aiscript.execFn(this.aiscript.scope.get(fn), []);
} catch (err) {}
}
@autobind
public registerCanvas(id: string, canvas: any) {
this.canvases[id] = canvas;
}
@autobind
public updatePageVar(name: string, value: any) {
const pageVar = this.pageVars.find(v => v.name === name);
if (pageVar !== undefined) {
pageVar.value = value;
if (this.pageVarUpdatedCallback) {
if (this.aiscript) this.aiscript.execFn(this.pageVarUpdatedCallback, [values.STR(name), utils.jsToVal(value)]);
}
} else {
throw new HpmlError(`No such page var '${name}'`);
}
}
@autobind
public updateRandomSeed(seed: string) {
this.opts.randomSeed = seed;
this.envVars.SEED = seed;
}
@autobind
private _interpolateScope(str: string, scope: HpmlScope) {
return str.replace(/{(.+?)}/g, match => {
const v = scope.getState(match.slice(1, -1).trim());
return v == null ? 'NULL' : v.toString();
});
}
@autobind
public evaluateVars(): Record<string, any> {
const values: Record<string, any> = {};
for (const [k, v] of Object.entries(this.envVars)) {
values[k] = v;
}
for (const v of this.pageVars) {
values[v.name] = v.value;
}
for (const v of this.variables) {
values[v.name] = this.evaluate(v, new HpmlScope([values]));
}
return values;
}
@autobind
private evaluate(expr: Expr, scope: HpmlScope): any {
if (isLiteralValue(expr)) {
if (expr.type === null) {
return null;
}
if (expr.type === 'number') {
return parseInt((expr.value as any), 10);
}
if (expr.type === 'text' || expr.type === 'multiLineText') {
return this._interpolateScope(expr.value || '', scope);
}
if (expr.type === 'textList') {
return this._interpolateScope(expr.value || '', scope).trim().split('\n');
}
if (expr.type === 'ref') {
return scope.getState(expr.value);
}
if (expr.type === 'aiScriptVar') {
if (this.aiscript) {
try {
return utils.valToJs(this.aiscript.scope.get(expr.value));
} catch (err) {
return null;
}
} else {
return null;
}
}
// Define user function
if (expr.type === 'fn') {
return {
slots: expr.value.slots.map(x => x.name),
exec: (slotArg: Record<string, any>) => {
return this.evaluate(expr.value.expression, scope.createChildScope(slotArg, expr.id));
}
} as Fn;
}
return;
}
// Call user function
if (expr.type.startsWith('fn:')) {
const fnName = expr.type.split(':')[1];
const fn = scope.getState(fnName);
const args = {} as Record<string, any>;
for (let i = 0; i < fn.slots.length; i++) {
const name = fn.slots[i];
args[name] = this.evaluate(expr.args[i], scope);
}
return fn.exec(args);
}
if (expr.args === undefined) return null;
const funcs = initHpmlLib(expr, scope, this.opts.randomSeed, this.opts.visitor);
// Call function
const fnName = expr.type;
const fn = (funcs as any)[fnName];
if (fn == null) {
throw new HpmlError(`No such function '${fnName}'`);
} else {
return fn(...expr.args.map(x => this.evaluate(x, scope)));
}
}
}

View File

@ -1,79 +0,0 @@
import { literalDefs, Type } from '.';
export type ExprBase = {
id: string;
};
// value
export type EmptyValue = ExprBase & {
type: null;
value: null;
};
export type TextValue = ExprBase & {
type: 'text';
value: string;
};
export type MultiLineTextValue = ExprBase & {
type: 'multiLineText';
value: string;
};
export type TextListValue = ExprBase & {
type: 'textList';
value: string;
};
export type NumberValue = ExprBase & {
type: 'number';
value: number;
};
export type RefValue = ExprBase & {
type: 'ref';
value: string; // value is variable name
};
export type AiScriptRefValue = ExprBase & {
type: 'aiScriptVar';
value: string; // value is variable name
};
export type UserFnValue = ExprBase & {
type: 'fn';
value: UserFnInnerValue;
};
type UserFnInnerValue = {
slots: {
name: string;
type: Type;
}[];
expression: Expr;
};
export type Value =
EmptyValue | TextValue | MultiLineTextValue | TextListValue | NumberValue | RefValue | AiScriptRefValue | UserFnValue;
export function isLiteralValue(expr: Expr): expr is Value {
if (expr.type == null) return true;
if (literalDefs[expr.type]) return true;
return false;
}
// call function
export type CallFn = ExprBase & { // "fn:hoge" or string
type: string;
args: Expr[];
value: null;
};
// variable
export type Variable = (Value | CallFn) & {
name: string;
};
// expression
export type Expr = Variable | Value | CallFn;

View File

@ -1,103 +0,0 @@
/**
* Hpml
*/
import autobind from 'autobind-decorator';
import { Hpml } from './evaluator';
import { funcDefs } from './lib';
export type Fn = {
slots: string[];
exec: (args: Record<string, any>) => ReturnType<Hpml['evaluate']>;
};
export type Type = 'string' | 'number' | 'boolean' | 'stringArray' | null;
export const literalDefs: Record<string, { out: any; category: string; icon: any; }> = {
text: { out: 'string', category: 'value', icon: 'fas fa-quote-right', },
multiLineText: { out: 'string', category: 'value', icon: 'fas fa-align-left', },
textList: { out: 'stringArray', category: 'value', icon: 'fas fa-list', },
number: { out: 'number', category: 'value', icon: 'fas fa-sort-numeric-up', },
ref: { out: null, category: 'value', icon: 'fas fa-magic', },
aiScriptVar: { out: null, category: 'value', icon: 'fas fa-magic', },
fn: { out: 'function', category: 'value', icon: 'fas fa-square-root-alt', },
};
export const blockDefs = [
...Object.entries(literalDefs).map(([k, v]) => ({
type: k, out: v.out, category: v.category, icon: v.icon
})),
...Object.entries(funcDefs).map(([k, v]) => ({
type: k, out: v.out, category: v.category, icon: v.icon
}))
];
export type PageVar = { name: string; value: any; type: Type; };
export const envVarsDef: Record<string, Type> = {
AI: 'string',
URL: 'string',
VERSION: 'string',
LOGIN: 'boolean',
NAME: 'string',
USERNAME: 'string',
USERID: 'string',
NOTES_COUNT: 'number',
FOLLOWERS_COUNT: 'number',
FOLLOWING_COUNT: 'number',
IS_CAT: 'boolean',
SEED: null,
YMD: 'string',
AISCRIPT_DISABLED: 'boolean',
NULL: null,
};
export class HpmlScope {
private layerdStates: Record<string, any>[];
public name: string;
constructor(layerdStates: HpmlScope['layerdStates'], name?: HpmlScope['name']) {
this.layerdStates = layerdStates;
this.name = name || 'anonymous';
}
@autobind
public createChildScope(states: Record<string, any>, name?: HpmlScope['name']): HpmlScope {
const layer = [states, ...this.layerdStates];
return new HpmlScope(layer, name);
}
/**
*
* @param name
*/
@autobind
public getState(name: string): any {
for (const later of this.layerdStates) {
const state = later[name];
if (state !== undefined) {
return state;
}
}
throw new HpmlError(
`No such variable '${name}' in scope '${this.name}'`, {
scope: this.layerdStates
});
}
}
export class HpmlError extends Error {
public info?: any;
constructor(message: string, info?: any) {
super(message);
this.info = info;
// Maintains proper stack trace for where our error was thrown (only available on V8)
if (Error.captureStackTrace) {
Error.captureStackTrace(this, HpmlError);
}
}
}

View File

@ -1,247 +0,0 @@
import tinycolor from 'tinycolor2';
import { Hpml } from './evaluator';
import { values, utils } from '@syuilo/aiscript';
import { Fn, HpmlScope } from '.';
import { Expr } from './expr';
import seedrandom from 'seedrandom';
/* TODO: https://www.chartjs.org/docs/latest/configuration/canvas-background.html#color
// https://stackoverflow.com/questions/38493564/chart-area-background-color-chartjs
Chart.pluginService.register({
beforeDraw: (chart, easing) => {
if (chart.config.options.chartArea && chart.config.options.chartArea.backgroundColor) {
const ctx = chart.chart.ctx;
ctx.save();
ctx.fillStyle = chart.config.options.chartArea.backgroundColor;
ctx.fillRect(0, 0, chart.chart.width, chart.chart.height);
ctx.restore();
}
}
});
*/
export function initAiLib(hpml: Hpml) {
return {
'MkPages:updated': values.FN_NATIVE(([callback]) => {
hpml.pageVarUpdatedCallback = (callback as values.VFn);
}),
'MkPages:get_canvas': values.FN_NATIVE(([id]) => {
utils.assertString(id);
const canvas = hpml.canvases[id.value];
const ctx = canvas.getContext('2d');
return values.OBJ(new Map([
['clear_rect', values.FN_NATIVE(([x, y, width, height]) => { ctx.clearRect(x.value, y.value, width.value, height.value); })],
['fill_rect', values.FN_NATIVE(([x, y, width, height]) => { ctx.fillRect(x.value, y.value, width.value, height.value); })],
['stroke_rect', values.FN_NATIVE(([x, y, width, height]) => { ctx.strokeRect(x.value, y.value, width.value, height.value); })],
['fill_text', values.FN_NATIVE(([text, x, y, width]) => { ctx.fillText(text.value, x.value, y.value, width ? width.value : undefined); })],
['stroke_text', values.FN_NATIVE(([text, x, y, width]) => { ctx.strokeText(text.value, x.value, y.value, width ? width.value : undefined); })],
['set_line_width', values.FN_NATIVE(([width]) => { ctx.lineWidth = width.value; })],
['set_font', values.FN_NATIVE(([font]) => { ctx.font = font.value; })],
['set_fill_style', values.FN_NATIVE(([style]) => { ctx.fillStyle = style.value; })],
['set_stroke_style', values.FN_NATIVE(([style]) => { ctx.strokeStyle = style.value; })],
['begin_path', values.FN_NATIVE(() => { ctx.beginPath(); })],
['close_path', values.FN_NATIVE(() => { ctx.closePath(); })],
['move_to', values.FN_NATIVE(([x, y]) => { ctx.moveTo(x.value, y.value); })],
['line_to', values.FN_NATIVE(([x, y]) => { ctx.lineTo(x.value, y.value); })],
['arc', values.FN_NATIVE(([x, y, radius, startAngle, endAngle]) => { ctx.arc(x.value, y.value, radius.value, startAngle.value, endAngle.value); })],
['rect', values.FN_NATIVE(([x, y, width, height]) => { ctx.rect(x.value, y.value, width.value, height.value); })],
['fill', values.FN_NATIVE(() => { ctx.fill(); })],
['stroke', values.FN_NATIVE(() => { ctx.stroke(); })],
]));
}),
'MkPages:chart': values.FN_NATIVE(([id, opts]) => {
/* TODO
utils.assertString(id);
utils.assertObject(opts);
const canvas = hpml.canvases[id.value];
const color = getComputedStyle(document.documentElement).getPropertyValue('--accent');
Chart.defaults.color = '#555';
const chart = new Chart(canvas, {
type: opts.value.get('type').value,
data: {
labels: opts.value.get('labels').value.map(x => x.value),
datasets: opts.value.get('datasets').value.map(x => ({
label: x.value.has('label') ? x.value.get('label').value : '',
data: x.value.get('data').value.map(x => x.value),
pointRadius: 0,
lineTension: 0,
borderWidth: 2,
borderColor: x.value.has('color') ? x.value.get('color') : color,
backgroundColor: tinycolor(x.value.has('color') ? x.value.get('color') : color).setAlpha(0.1).toRgbString(),
}))
},
options: {
responsive: false,
devicePixelRatio: 1.5,
title: {
display: opts.value.has('title'),
text: opts.value.has('title') ? opts.value.get('title').value : '',
fontSize: 14,
},
layout: {
padding: {
left: 32,
right: 32,
top: opts.value.has('title') ? 16 : 32,
bottom: 16
}
},
legend: {
display: opts.value.get('datasets').value.filter(x => x.value.has('label') && x.value.get('label').value).length === 0 ? false : true,
position: 'bottom',
labels: {
boxWidth: 16,
}
},
tooltips: {
enabled: false,
},
chartArea: {
backgroundColor: '#fff'
},
...(opts.value.get('type').value === 'radar' ? {
scale: {
ticks: {
display: opts.value.has('show_tick_label') ? opts.value.get('show_tick_label').value : false,
min: opts.value.has('min') ? opts.value.get('min').value : undefined,
max: opts.value.has('max') ? opts.value.get('max').value : undefined,
maxTicksLimit: 8,
},
pointLabels: {
fontSize: 12
}
}
} : {
scales: {
yAxes: [{
ticks: {
display: opts.value.has('show_tick_label') ? opts.value.get('show_tick_label').value : true,
min: opts.value.has('min') ? opts.value.get('min').value : undefined,
max: opts.value.has('max') ? opts.value.get('max').value : undefined,
}
}]
}
})
}
});
*/
}),
};
}
export const funcDefs: Record<string, { in: any[]; out: any; category: string; icon: any; }> = {
if: { in: ['boolean', 0, 0], out: 0, category: 'flow', icon: 'fas fa-share-alt' },
for: { in: ['number', 'function'], out: null, category: 'flow', icon: 'fas fa-recycle' },
not: { in: ['boolean'], out: 'boolean', category: 'logical', icon: 'fas fa-flag' },
or: { in: ['boolean', 'boolean'], out: 'boolean', category: 'logical', icon: 'fas fa-flag' },
and: { in: ['boolean', 'boolean'], out: 'boolean', category: 'logical', icon: 'fas fa-flag' },
add: { in: ['number', 'number'], out: 'number', category: 'operation', icon: 'fas fa-plus' },
subtract: { in: ['number', 'number'], out: 'number', category: 'operation', icon: 'fas fa-minus' },
multiply: { in: ['number', 'number'], out: 'number', category: 'operation', icon: 'fas fa-times' },
divide: { in: ['number', 'number'], out: 'number', category: 'operation', icon: 'fas fa-divide' },
mod: { in: ['number', 'number'], out: 'number', category: 'operation', icon: 'fas fa-divide' },
round: { in: ['number'], out: 'number', category: 'operation', icon: 'fas fa-calculator' },
eq: { in: [0, 0], out: 'boolean', category: 'comparison', icon: 'fas fa-equals' },
notEq: { in: [0, 0], out: 'boolean', category: 'comparison', icon: 'fas fa-not-equal' },
gt: { in: ['number', 'number'], out: 'boolean', category: 'comparison', icon: 'fas fa-greater-than' },
lt: { in: ['number', 'number'], out: 'boolean', category: 'comparison', icon: 'fas fa-less-than' },
gtEq: { in: ['number', 'number'], out: 'boolean', category: 'comparison', icon: 'fas fa-greater-than-equal' },
ltEq: { in: ['number', 'number'], out: 'boolean', category: 'comparison', icon: 'fas fa-less-than-equal' },
strLen: { in: ['string'], out: 'number', category: 'text', icon: 'fas fa-quote-right' },
strPick: { in: ['string', 'number'], out: 'string', category: 'text', icon: 'fas fa-quote-right' },
strReplace: { in: ['string', 'string', 'string'], out: 'string', category: 'text', icon: 'fas fa-quote-right' },
strReverse: { in: ['string'], out: 'string', category: 'text', icon: 'fas fa-quote-right' },
join: { in: ['stringArray', 'string'], out: 'string', category: 'text', icon: 'fas fa-quote-right' },
stringToNumber: { in: ['string'], out: 'number', category: 'convert', icon: 'fas fa-exchange-alt' },
numberToString: { in: ['number'], out: 'string', category: 'convert', icon: 'fas fa-exchange-alt' },
splitStrByLine: { in: ['string'], out: 'stringArray', category: 'convert', icon: 'fas fa-exchange-alt' },
pick: { in: [null, 'number'], out: null, category: 'list', icon: 'fas fa-indent' },
listLen: { in: [null], out: 'number', category: 'list', icon: 'fas fa-indent' },
rannum: { in: ['number', 'number'], out: 'number', category: 'random', icon: 'fas fa-dice' },
dailyRannum: { in: ['number', 'number'], out: 'number', category: 'random', icon: 'fas fa-dice' },
seedRannum: { in: [null, 'number', 'number'], out: 'number', category: 'random', icon: 'fas fa-dice' },
random: { in: ['number'], out: 'boolean', category: 'random', icon: 'fas fa-dice' },
dailyRandom: { in: ['number'], out: 'boolean', category: 'random', icon: 'fas fa-dice' },
seedRandom: { in: [null, 'number'], out: 'boolean', category: 'random', icon: 'fas fa-dice' },
randomPick: { in: [0], out: 0, category: 'random', icon: 'fas fa-dice' },
dailyRandomPick: { in: [0], out: 0, category: 'random', icon: 'fas fa-dice' },
seedRandomPick: { in: [null, 0], out: 0, category: 'random', icon: 'fas fa-dice' },
DRPWPM: { in: ['stringArray'], out: 'string', category: 'random', icon: 'fas fa-dice' }, // dailyRandomPickWithProbabilityMapping
};
export function initHpmlLib(expr: Expr, scope: HpmlScope, randomSeed: string, visitor?: any) {
const date = new Date();
const day = `${visitor ? visitor.id : ''} ${date.getFullYear()}/${date.getMonth() + 1}/${date.getDate()}`;
// SHOULD be fine to ignore since it's intended + function shape isn't defined
// eslint-disable-next-line @typescript-eslint/ban-types
const funcs: Record<string, Function> = {
not: (a: boolean) => !a,
or: (a: boolean, b: boolean) => a || b,
and: (a: boolean, b: boolean) => a && b,
eq: (a: any, b: any) => a === b,
notEq: (a: any, b: any) => a !== b,
gt: (a: number, b: number) => a > b,
lt: (a: number, b: number) => a < b,
gtEq: (a: number, b: number) => a >= b,
ltEq: (a: number, b: number) => a <= b,
if: (bool: boolean, a: any, b: any) => bool ? a : b,
for: (times: number, fn: Fn) => {
const result: any[] = [];
for (let i = 0; i < times; i++) {
result.push(fn.exec({
[fn.slots[0]]: i + 1,
}));
}
return result;
},
add: (a: number, b: number) => a + b,
subtract: (a: number, b: number) => a - b,
multiply: (a: number, b: number) => a * b,
divide: (a: number, b: number) => a / b,
mod: (a: number, b: number) => a % b,
round: (a: number) => Math.round(a),
strLen: (a: string) => a.length,
strPick: (a: string, b: number) => a[b - 1],
strReplace: (a: string, b: string, c: string) => a.split(b).join(c),
strReverse: (a: string) => a.split('').reverse().join(''),
join: (texts: string[], separator: string) => texts.join(separator || ''),
stringToNumber: (a: string) => parseInt(a),
numberToString: (a: number) => a.toString(),
splitStrByLine: (a: string) => a.split('\n'),
pick: (list: any[], i: number) => list[i - 1],
listLen: (list: any[]) => list.length,
random: (probability: number) => Math.floor(seedrandom(`${randomSeed}:${expr.id}`)() * 100) < probability,
rannum: (min: number, max: number) => min + Math.floor(seedrandom(`${randomSeed}:${expr.id}`)() * (max - min + 1)),
randomPick: (list: any[]) => list[Math.floor(seedrandom(`${randomSeed}:${expr.id}`)() * list.length)],
dailyRandom: (probability: number) => Math.floor(seedrandom(`${day}:${expr.id}`)() * 100) < probability,
dailyRannum: (min: number, max: number) => min + Math.floor(seedrandom(`${day}:${expr.id}`)() * (max - min + 1)),
dailyRandomPick: (list: any[]) => list[Math.floor(seedrandom(`${day}:${expr.id}`)() * list.length)],
seedRandom: (seed: any, probability: number) => Math.floor(seedrandom(seed)() * 100) < probability,
seedRannum: (seed: any, min: number, max: number) => min + Math.floor(seedrandom(seed)() * (max - min + 1)),
seedRandomPick: (seed: any, list: any[]) => list[Math.floor(seedrandom(seed)() * list.length)],
DRPWPM: (list: string[]) => {
const xs: any[] = [];
let totalFactor = 0;
for (const x of list) {
const parts = x.split(' ');
const factor = parseInt(parts.pop()!, 10);
const text = parts.join(' ');
totalFactor += factor;
xs.push({ factor, text });
}
const r = seedrandom(`${day}:${expr.id}`)() * totalFactor;
let stackedFactor = 0;
for (const x of xs) {
if (r >= stackedFactor && r <= stackedFactor + x.factor) {
return x.text;
} else {
stackedFactor += x.factor;
}
}
return xs[0].text;
},
};
return funcs;
}

View File

@ -1,189 +0,0 @@
import autobind from 'autobind-decorator';
import { Type, envVarsDef, PageVar } from '.';
import { Expr, isLiteralValue, Variable } from './expr';
import { funcDefs } from './lib';
type TypeError = {
arg: number;
expect: Type;
actual: Type;
};
/**
* Hpml type checker
*/
export class HpmlTypeChecker {
public variables: Variable[];
public pageVars: PageVar[];
constructor(variables: HpmlTypeChecker['variables'] = [], pageVars: HpmlTypeChecker['pageVars'] = []) {
this.variables = variables;
this.pageVars = pageVars;
}
@autobind
public typeCheck(v: Expr): TypeError | null {
if (isLiteralValue(v)) return null;
const def = funcDefs[v.type || ''];
if (def == null) {
throw new Error('Unknown type: ' + v.type);
}
const generic: Type[] = [];
for (let i = 0; i < def.in.length; i++) {
const arg = def.in[i];
const type = this.infer(v.args[i]);
if (type === null) continue;
if (typeof arg === 'number') {
if (generic[arg] === undefined) {
generic[arg] = type;
} else if (type !== generic[arg]) {
return {
arg: i,
expect: generic[arg],
actual: type
};
}
} else if (type !== arg) {
return {
arg: i,
expect: arg,
actual: type
};
}
}
return null;
}
@autobind
public getExpectedType(v: Expr, slot: number): Type {
const def = funcDefs[v.type || ''];
if (def == null) {
throw new Error('Unknown type: ' + v.type);
}
const generic: Type[] = [];
for (let i = 0; i < def.in.length; i++) {
const arg = def.in[i];
const type = this.infer(v.args[i]);
if (type === null) continue;
if (typeof arg === 'number') {
if (generic[arg] === undefined) {
generic[arg] = type;
}
}
}
if (typeof def.in[slot] === 'number') {
return generic[def.in[slot]] || null;
} else {
return def.in[slot];
}
}
@autobind
public infer(v: Expr): Type {
if (v.type === null) return null;
if (v.type === 'text') return 'string';
if (v.type === 'multiLineText') return 'string';
if (v.type === 'textList') return 'stringArray';
if (v.type === 'number') return 'number';
if (v.type === 'ref') {
const variable = this.variables.find(va => va.name === v.value);
if (variable) {
return this.infer(variable);
}
const pageVar = this.pageVars.find(va => va.name === v.value);
if (pageVar) {
return pageVar.type;
}
const envVar = envVarsDef[v.value || ''];
if (envVar !== undefined) {
return envVar;
}
return null;
}
if (v.type === 'aiScriptVar') return null;
if (v.type === 'fn') return null; // todo
if (v.type.startsWith('fn:')) return null; // todo
const generic: Type[] = [];
const def = funcDefs[v.type];
for (let i = 0; i < def.in.length; i++) {
const arg = def.in[i];
if (typeof arg === 'number') {
const type = this.infer(v.args[i]);
if (generic[arg] === undefined) {
generic[arg] = type;
} else {
if (type !== generic[arg]) {
generic[arg] = null;
}
}
}
}
if (typeof def.out === 'number') {
return generic[def.out];
} else {
return def.out;
}
}
@autobind
public getVarByName(name: string): Variable {
const v = this.variables.find(x => x.name === name);
if (v !== undefined) {
return v;
} else {
throw new Error(`No such variable '${name}'`);
}
}
@autobind
public getVarsByType(type: Type): Variable[] {
if (type == null) return this.variables;
return this.variables.filter(x => (this.infer(x) === null) || (this.infer(x) === type));
}
@autobind
public getEnvVarsByType(type: Type): string[] {
if (type == null) return Object.keys(envVarsDef);
return Object.entries(envVarsDef).filter(([k, v]) => v === null || type === v).map(([k, v]) => k);
}
@autobind
public getPageVarsByType(type: Type): string[] {
if (type == null) return this.pageVars.map(v => v.name);
return this.pageVars.filter(v => type === v.type).map(v => v.name);
}
@autobind
public isUsedName(name: string) {
if (this.variables.some(v => v.name === name)) {
return true;
}
if (this.pageVars.some(v => v.name === name)) {
return true;
}
if (envVarsDef[name]) {
return true;
}
return false;
}
}