Change styles
This commit is contained in:
parent
301c8540b4
commit
5f5ae25060
@ -3,7 +3,8 @@ output: static
|
|||||||
template: static/template.html
|
template: static/template.html
|
||||||
|
|
||||||
headings:
|
headings:
|
||||||
h1: text-4xl mb-4 font-black
|
h1: text-3xl mb-4 font-display opacity-90
|
||||||
h2: text-3xl mt-8 mb-4 font-bold
|
h2: text-2xl mt-10 mb-4 font-display opacity-90
|
||||||
h3: text-2xl mt-8 mb-4 font-medium
|
h3: text-xl mt-10 mb-4 font-display opacity-90
|
||||||
|
|
||||||
|
file_tree_title_classes: "uppercase text-sm font-display"
|
||||||
|
80
md/learn/basics/comments.md
Normal file
80
md/learn/basics/comments.md
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
# Comments
|
||||||
|
|
||||||
|
You may have noticed that in some code examples there are some
|
||||||
|
lines of text explaining the code:
|
||||||
|
|
||||||
|
```thp
|
||||||
|
// This is the variable
|
||||||
|
val person = "John"
|
||||||
|
```
|
||||||
|
|
||||||
|
Comments are used to explain what the code does. Anything written
|
||||||
|
in a comment is ignored by THP.
|
||||||
|
|
||||||
|
## Single line comments
|
||||||
|
|
||||||
|
As the name says, these comments span only 1 line. To create one write
|
||||||
|
two slashes together `//`. Everything after the slashes and before
|
||||||
|
the newline will be ignored.
|
||||||
|
|
||||||
|
```thp
|
||||||
|
// This is a single line comment
|
||||||
|
// You can write anything you want here, although it's usually
|
||||||
|
// used to describe the code
|
||||||
|
|
||||||
|
// The commend ends where the line ends,
|
||||||
|
so this line will not be ignored by THP, and will throw an error
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Multi line comments
|
||||||
|
|
||||||
|
As the name says, these comments can span multiple lines.
|
||||||
|
|
||||||
|
They have 2 components: a start and a end. To start a multiline comment
|
||||||
|
write a slash and asterisk `/*`, and to end the comment, the inverse `*/`
|
||||||
|
|
||||||
|
```thp
|
||||||
|
/*
|
||||||
|
This is a multiline comment.
|
||||||
|
I can write whatever I want here, and across multiple
|
||||||
|
lines, as long as I'm before the closing characters (* /)
|
||||||
|
*/
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Using comments to prevent code execution
|
||||||
|
|
||||||
|
Since comments are ignored by THP, we can use them to prevent certain
|
||||||
|
parts of the code from running.
|
||||||
|
|
||||||
|
Let's say we have this script:
|
||||||
|
|
||||||
|
```thp
|
||||||
|
print("Hello John")
|
||||||
|
print("How's your day going?")
|
||||||
|
```
|
||||||
|
|
||||||
|
If I wanted the 2nd line not to execute, I can use a comment:
|
||||||
|
|
||||||
|
```thp
|
||||||
|
print("Hello John")
|
||||||
|
// print("How's your day going?")
|
||||||
|
```
|
||||||
|
|
||||||
|
Now the second line is ignored, and the message is not printed.
|
||||||
|
|
||||||
|
The same can be done with multiline comments.
|
||||||
|
|
||||||
|
|
||||||
|
```thp
|
||||||
|
print("Hello John")
|
||||||
|
/*
|
||||||
|
print("How's your day going?")
|
||||||
|
*/
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
127
md/learn/basics/datatypes.md
Normal file
127
md/learn/basics/datatypes.md
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
# Datatypes
|
||||||
|
|
||||||
|
Programming is comprised of 2 basic things: instructions and data.
|
||||||
|
|
||||||
|
If we compare a program to a cake recipe, the instructions are the steps
|
||||||
|
(**pour** flour, **add** water, **add** egg, **mix**) and the data are the ingredients
|
||||||
|
themselves (flour, water, egg).
|
||||||
|
|
||||||
|
![Image](Image)
|
||||||
|
|
||||||
|
Then, we can describe the recipe in terms of instructions and data. For example,
|
||||||
|
"mix flour and egg to produce dough".
|
||||||
|
|
||||||
|
![Image](Image)
|
||||||
|
|
||||||
|
All code is like a recipe: A list of instructions and data that, when combined
|
||||||
|
correctly, are able to transform a input to an output. Many advanced concepts
|
||||||
|
are just ways to organize and abstract those instructions and data.
|
||||||
|
|
||||||
|
|
||||||
|
## Classifying datatypes
|
||||||
|
|
||||||
|
As with food, datatypes can be classified. Just like there are fruits, vegetables,
|
||||||
|
oils, there are `numbers`, `text`, `"booleans"`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Int
|
||||||
|
|
||||||
|
Int is an abbreviation for "integer numbers", which are numbers without a fractional component.
|
||||||
|
They can be positive or negative.
|
||||||
|
|
||||||
|
In code, they are written just like numbers:
|
||||||
|
|
||||||
|
```thp
|
||||||
|
val age = 33
|
||||||
|
val children = 0
|
||||||
|
val money = -15000
|
||||||
|
```
|
||||||
|
|
||||||
|
You can use underscores to help you differentiate thousands, millions, etc.
|
||||||
|
However, there cannot be spaces in between
|
||||||
|
|
||||||
|
```thp
|
||||||
|
val studentDebt = 3_500_000_000_000 // Valid
|
||||||
|
val invalid = 3 500 000 000 000 // Invalid, will throw an error
|
||||||
|
```
|
||||||
|
|
||||||
|
The common operations can be done as in math:
|
||||||
|
|
||||||
|
```thp
|
||||||
|
val result1 = 10 + 20
|
||||||
|
val result2 = 1779 * 2 - (55 / 5)
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Float
|
||||||
|
|
||||||
|
Float is an abbreviation for "floating point numbers". In simplified terms, these are numbers
|
||||||
|
**with** a fractional component.
|
||||||
|
|
||||||
|
They are written with a dot `.` to separate the whole part and the fraction.
|
||||||
|
|
||||||
|
```thp
|
||||||
|
val pi = 3.141592
|
||||||
|
val epsilon = 2.775557
|
||||||
|
```
|
||||||
|
|
||||||
|
Underscore can also be used:
|
||||||
|
|
||||||
|
```thp
|
||||||
|
val reallyLongNumber = 23_870_000.443_879
|
||||||
|
```
|
||||||
|
|
||||||
|
Common operations can be performed the same way:
|
||||||
|
|
||||||
|
```thp
|
||||||
|
val value1 = 552.23 - 32
|
||||||
|
val value2 = 3.2 * (-0.22 + 23.334) / 0.5
|
||||||
|
// etc.
|
||||||
|
```
|
||||||
|
|
||||||
|
### String
|
||||||
|
|
||||||
|
A string of letters (technically, characters). Strings are used to represent text,
|
||||||
|
and are wrapped in quotation marks.
|
||||||
|
|
||||||
|
```thp
|
||||||
|
val name = "John"
|
||||||
|
val lastName = "Doe"
|
||||||
|
|
||||||
|
val greeting = "Hello"
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Concatenation
|
||||||
|
|
||||||
|
Strings cannot be added, substracted, multiplied, divided.
|
||||||
|
They have another operation, called "concatenation".
|
||||||
|
|
||||||
|
Concatenation "joins" two strings, for example, the concatenation of
|
||||||
|
`"human"` and `"kind"` is `"humankind"`.
|
||||||
|
|
||||||
|
As it is a common operation, string concatenation reuses the operation
|
||||||
|
for addition `+`.
|
||||||
|
|
||||||
|
```thp
|
||||||
|
val string = "human" + "kind"
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Boolean
|
||||||
|
|
||||||
|
A boolean represents something that can only be in one of two states.
|
||||||
|
|
||||||
|
Booleans are useful in conditionals, which will be explained later.
|
||||||
|
|
||||||
|
|
||||||
|
```thp
|
||||||
|
val condition = true
|
||||||
|
val isSunny = false
|
||||||
|
|
||||||
|
if isSunny {
|
||||||
|
doSomething()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
60
md/learn/basics/hello-world.md
Normal file
60
md/learn/basics/hello-world.md
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
# Hello, world!
|
||||||
|
|
||||||
|
This pages shows you how to write and run your first THP script.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
You will need to have PHP and THP installed. If you haven't already, see the
|
||||||
|
install page.
|
||||||
|
|
||||||
|
## Writing the program
|
||||||
|
|
||||||
|
Create a new file called `hello.thp`, and inside write the following (you can
|
||||||
|
copy and paste):
|
||||||
|
|
||||||
|
```thp
|
||||||
|
print("Hello, world!")
|
||||||
|
```
|
||||||
|
|
||||||
|
Then, save the code.
|
||||||
|
|
||||||
|
## Running the program
|
||||||
|
|
||||||
|
Open a terminal in the folder where you created the file `hello.thp`.
|
||||||
|
Then write the following command and press enter:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
thp hello.thp
|
||||||
|
```
|
||||||
|
|
||||||
|
This will run the program, and produce the following result:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
Hello, world!
|
||||||
|
```
|
||||||
|
|
||||||
|
Congratulations! You just wrote your first THP program!
|
||||||
|
|
||||||
|
## Explaining the program
|
||||||
|
|
||||||
|
Now let's understand the code.
|
||||||
|
|
||||||
|
```thp
|
||||||
|
print("Hello, world!")
|
||||||
|
```
|
||||||
|
|
||||||
|
There are 2 essential components:
|
||||||
|
|
||||||
|
- `print` - print is a "function", it takes some value and performs some action with it.
|
||||||
|
In this case, it takes a text and displays it in the terminal.
|
||||||
|
- `"Hello, world!"` - Is the text that the function `print` takes, and displays in
|
||||||
|
the terminal. Note that it is enclosed in quotation marks.
|
||||||
|
|
||||||
|
## What to do next
|
||||||
|
|
||||||
|
You can now experiment with the program you wrote. What happens if you change the text?
|
||||||
|
What if you don't put quotation marks? And what are the parenthesis for?
|
||||||
|
|
||||||
|
To continue learning about THP, continue to the next page, where you'll learn
|
||||||
|
about "datatypes".
|
||||||
|
|
64
md/learn/basics/io.md
Normal file
64
md/learn/basics/io.md
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
# Input & Output
|
||||||
|
|
||||||
|
At the end of the day, a program takes some input,
|
||||||
|
and transform it to some output. We will explore how to
|
||||||
|
receive data, and also present it.
|
||||||
|
|
||||||
|
## Output
|
||||||
|
|
||||||
|
There are many ways to show the result of our programs.
|
||||||
|
One of them is called `standard output`, which in simplified
|
||||||
|
terms, is the terminal from where we run our program.
|
||||||
|
|
||||||
|
### `print`
|
||||||
|
|
||||||
|
Create an empty file, and name it `hello.php`. We will create
|
||||||
|
a program that shows a result to our screen.
|
||||||
|
|
||||||
|
Inside `hello.php` write the following code:
|
||||||
|
|
||||||
|
```thp
|
||||||
|
print("Hello")
|
||||||
|
```
|
||||||
|
|
||||||
|
Then, open a terminal and run the program with the `thp` command.
|
||||||
|
After you press ENTER, you will see in the terminal the text "Hello".
|
||||||
|
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ thp hello.thp # Copy this command and run it
|
||||||
|
Hello # This is the output of our program
|
||||||
|
```
|
||||||
|
|
||||||
|
The thp function `print` allows us to display something in the terminal.
|
||||||
|
|
||||||
|
If you change the `hello.php` file, and run it, you'll see how it changes.
|
||||||
|
|
||||||
|
```thp
|
||||||
|
print(322)
|
||||||
|
```
|
||||||
|
```sh
|
||||||
|
$ thp hello.php
|
||||||
|
322
|
||||||
|
```
|
||||||
|
|
||||||
|
Or, if you copy `print` multiple times, each will show something in the screen.
|
||||||
|
|
||||||
|
```thp
|
||||||
|
print("Hello")
|
||||||
|
print("This is an example")
|
||||||
|
print("of having many prints")
|
||||||
|
```
|
||||||
|
```sh
|
||||||
|
$ thp hello.php
|
||||||
|
Hello
|
||||||
|
This is an example
|
||||||
|
of having many prints
|
||||||
|
```
|
||||||
|
|
||||||
|
### Using `print` in a larger program
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
5
md/learn/basics/operators.md
Normal file
5
md/learn/basics/operators.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# Operators
|
||||||
|
|
||||||
|
Some common operators
|
||||||
|
|
||||||
|
|
72
md/learn/basics/the-compiler.md
Normal file
72
md/learn/basics/the-compiler.md
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
# The compiler
|
||||||
|
|
||||||
|
The compiler is the program that takes your THP code and converts it
|
||||||
|
into something that the computer can run (in this case, PHP code).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
The compiler reads your code and tries to understand it.
|
||||||
|
When it can't understand some part, it will ask you to clarify what
|
||||||
|
you meant, with an error.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Compile time vs runtime
|
||||||
|
|
||||||
|
Compile time is when you build your program.
|
||||||
|
|
||||||
|
Runtime is when you run your program.
|
||||||
|
|
||||||
|
To make an analogy with cars, compile time would be the factory,
|
||||||
|
while runtime would be using the finished car.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
The compiler is very strict. If it finds any errors during compile time
|
||||||
|
it will refuse to build the program.
|
||||||
|
|
||||||
|
|
||||||
|
### Compile time errors
|
||||||
|
|
||||||
|
Compile time errors are errors that happen while the compiler is
|
||||||
|
building your program. In the car analogy, a compile error would happen
|
||||||
|
if there's an error in the "blueprint"
|
||||||
|
|
||||||
|
|
||||||
|
### Runtime errors
|
||||||
|
|
||||||
|
These are errors that happen to the built program, or in this case,
|
||||||
|
the finished car. It would be like the car blowing up while on the highway.
|
||||||
|
|
||||||
|
To minimize the amount of runtime errors the compiler tries to catch them all
|
||||||
|
during compile time. It's better if it fails in the factory than in the
|
||||||
|
real world.
|
||||||
|
|
||||||
|
|
||||||
|
## The compiler and datatypes
|
||||||
|
|
||||||
|
The first measure the compiler takes is to check that all the datatypes
|
||||||
|
match. If an operation requires a number, you can't just give it a string.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
For example, if we wanted to add a number to a string, we would get an
|
||||||
|
error:
|
||||||
|
|
||||||
|
```thp
|
||||||
|
50 + "hello" // Error: The `+` operator expects two Numbers,
|
||||||
|
// but an String was found.
|
||||||
|
```
|
||||||
|
|
||||||
|
This way, we can assure that many errors are avoided (since it doesn't
|
||||||
|
really make sense to add a number to a text).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
139
md/learn/basics/variables.md
Normal file
139
md/learn/basics/variables.md
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
# Variables
|
||||||
|
|
||||||
|
Variables allows us to store values under a name, so that we can use them
|
||||||
|
later.
|
||||||
|
|
||||||
|
For example, in a program we could have the name of our user, and use it
|
||||||
|
multiple times:
|
||||||
|
|
||||||
|
```thp
|
||||||
|
print("Hello, where's Joe?")
|
||||||
|
print("How old is Joe?")
|
||||||
|
print("Do you know if Joe has kids?")
|
||||||
|
```
|
||||||
|
|
||||||
|
We are using the same value `Joe` many times. Each time we use it we have
|
||||||
|
to type `Joe`. But what happens if we needed to use a different name?
|
||||||
|
We'd have to change the name everywhere in our code!
|
||||||
|
|
||||||
|
```thp
|
||||||
|
print("Hello, where's Jane?")
|
||||||
|
print("How old is Jane?")
|
||||||
|
print("Do you know if Jane has kids?")
|
||||||
|
```
|
||||||
|
|
||||||
|
## Variables to the rescue
|
||||||
|
|
||||||
|
With a variable we can store values so we can use them later, or use them
|
||||||
|
in multiple times.
|
||||||
|
|
||||||
|
In the previous code, we can use a variable to store the person's name,
|
||||||
|
and then use it everywhere.
|
||||||
|
|
||||||
|
```thp
|
||||||
|
// This is the variable
|
||||||
|
val person = "John"
|
||||||
|
|
||||||
|
print("Hello, where's {person}?")
|
||||||
|
print("How old is {person}?")
|
||||||
|
print("Do you know if Joe has {person}?")
|
||||||
|
```
|
||||||
|
|
||||||
|
Now, instead of writing `"John"` every time, we write the name of the
|
||||||
|
variable instead.
|
||||||
|
|
||||||
|
If we wanted to change the person's name to "Jane", we just need to change
|
||||||
|
it in one place: the variable
|
||||||
|
|
||||||
|
```thp
|
||||||
|
// We change this
|
||||||
|
val person = "Jane"
|
||||||
|
|
||||||
|
// And all these lines will use the new value
|
||||||
|
print("Hello, where's {person}?")
|
||||||
|
print("How old is {person}?")
|
||||||
|
print("Do you know if Joe has {person}?")
|
||||||
|
```
|
||||||
|
|
||||||
|
## Variable rules
|
||||||
|
|
||||||
|
To use a variable we do the following:
|
||||||
|
|
||||||
|
- Write the special word `val`
|
||||||
|
- Write the name of our variable
|
||||||
|
- Write the equal sign `=`
|
||||||
|
- Write the value of our variable
|
||||||
|
|
||||||
|
```thp
|
||||||
|
val person = "Jane"
|
||||||
|
/* --- ------ - ------
|
||||||
|
| | | +- The value of our variable
|
||||||
|
| | +----- The equal sign
|
||||||
|
| +---------- The name of our variable
|
||||||
|
+--------------- The special word (keyword) val
|
||||||
|
*/
|
||||||
|
```
|
||||||
|
|
||||||
|
The value can be anything: ints, floats, string, bools, even other variables and operations!
|
||||||
|
|
||||||
|
```thp
|
||||||
|
val variable_1 = 322
|
||||||
|
val variable_2 = 123.456
|
||||||
|
val variable_3 = "a text"
|
||||||
|
val variable_4 = false
|
||||||
|
val variable_5 = variable_1 + variable 2
|
||||||
|
```
|
||||||
|
|
||||||
|
## Variable name rules
|
||||||
|
|
||||||
|
- Starts with a lowercase letter (a-z) or underscore (`_`)
|
||||||
|
- Then can have any letter (a-zA-Z), underscore (`_`) or number (0-9)
|
||||||
|
- Cannot have spaces
|
||||||
|
- Cannot have the same name as a keyword (for example, the `val` keyword)
|
||||||
|
|
||||||
|
|
||||||
|
Some examples of valid variable names:
|
||||||
|
|
||||||
|
```thp
|
||||||
|
val name = ...
|
||||||
|
val age = ...
|
||||||
|
val my_name = ...
|
||||||
|
val many_words_joined_by_underscores = ...
|
||||||
|
val person_2 = ...
|
||||||
|
val person_3 = ...
|
||||||
|
```
|
||||||
|
|
||||||
|
Some invalid variables and why they are invalid:
|
||||||
|
|
||||||
|
```thp
|
||||||
|
val 1name = ... // Invalid: starts with a number
|
||||||
|
val 123_person = ... // Invalid: starts with a number
|
||||||
|
val val = ... // Invalid: same name as a keyword (val)
|
||||||
|
val Person = ... // Invalid: starts with an uppercase letter
|
||||||
|
val person name = ... // Invalid: contains whitespace
|
||||||
|
val +@name = ... // Invalid: contains non-letters (+@)
|
||||||
|
val name🫠 = ... // Invalid: contains emoji (🫠)
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Variable reassignment
|
||||||
|
|
||||||
|
When you create a new variable with the same name of an old variable,
|
||||||
|
the old is "replaced" with the new one.
|
||||||
|
|
||||||
|
```thp
|
||||||
|
val person_name = "John"
|
||||||
|
print(person_name) // Will print "John"
|
||||||
|
|
||||||
|
val person_name = "Jane"
|
||||||
|
print(person_name) // Will print "Jane"
|
||||||
|
```
|
||||||
|
|
||||||
|
This will have some implications on the future, but for now you should
|
||||||
|
now that you will always use the value of the last variable you define.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
0
md/learn/flow-control/break-continue.md
Normal file
0
md/learn/flow-control/break-continue.md
Normal file
3
md/learn/flow-control/conditionals.md
Normal file
3
md/learn/flow-control/conditionals.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# Conditionals
|
||||||
|
|
||||||
|
|
0
md/learn/flow-control/foreach.md
Normal file
0
md/learn/flow-control/foreach.md
Normal file
0
md/learn/flow-control/if-expresions.md
Normal file
0
md/learn/flow-control/if-expresions.md
Normal file
0
md/learn/flow-control/match.md
Normal file
0
md/learn/flow-control/match.md
Normal file
0
md/learn/flow-control/while.md
Normal file
0
md/learn/flow-control/while.md
Normal file
71
md/learn/functions/parameters.md
Normal file
71
md/learn/functions/parameters.md
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
# Function parameters
|
||||||
|
|
||||||
|
|
||||||
|
## Immutable reference
|
||||||
|
|
||||||
|
```thp
|
||||||
|
fun add_25(Array[Int] numbers) {
|
||||||
|
numbers.push(25) // Error: `numbers` is immutable
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
When using a regular type as a parameter, only it's immutable
|
||||||
|
properties can be used inside the function
|
||||||
|
|
||||||
|
```thp
|
||||||
|
fun count(Array[Int] numbers) -> Int {
|
||||||
|
val items_count = numbers.size() // Ok, `size` is pure
|
||||||
|
|
||||||
|
items_count
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Mutable reference
|
||||||
|
|
||||||
|
```thp
|
||||||
|
fun add_25(&Array[Int] numbers) {
|
||||||
|
numbers.push(25) // Ok, will also mutate the original array
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Placing a `&` before the type makes the parameter a mutable
|
||||||
|
reference. Mutable methods can be used, and the original
|
||||||
|
data **will** be mutated.
|
||||||
|
|
||||||
|
The callee *must* also use `&`.
|
||||||
|
|
||||||
|
```thp
|
||||||
|
val numbers = Array(1, 2, 3, 4)
|
||||||
|
|
||||||
|
add_25(&numbers) // Pass `numbers` as reference.
|
||||||
|
|
||||||
|
print(numbers(4)) // `Some(25)`
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Clone
|
||||||
|
|
||||||
|
```thp
|
||||||
|
fun add_25(clone Array[Int] numbers) {
|
||||||
|
numbers.push(25) // Ok, the original array is unaffected
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Using the `clone` keyword before the type creates a mutable copy
|
||||||
|
of the parameter. The original data will **not** be mutated.
|
||||||
|
|
||||||
|
|
||||||
|
```thp
|
||||||
|
val numbers = Array(1, 2, 3, 4)
|
||||||
|
|
||||||
|
add_25(&numbers) // Pass `numbers` as reference.
|
||||||
|
|
||||||
|
print(numbers(4)) // None
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
201
md/learn/ideas/idea_1.md
Normal file
201
md/learn/ideas/idea_1.md
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
# Idea 1
|
||||||
|
|
||||||
|
|
||||||
|
var x = 20
|
||||||
|
val y = 30
|
||||||
|
|
||||||
|
type Something = ...
|
||||||
|
|
||||||
|
Something s1 = ...
|
||||||
|
Something s2 = s1
|
||||||
|
|
||||||
|
|
||||||
|
// Passes `some` by reference, but it's immutable. Cannot call mutable methods
|
||||||
|
// or use it in mutable operations
|
||||||
|
fun do_something(Something some) -> Bool {}
|
||||||
|
do_something(s1)
|
||||||
|
|
||||||
|
// Passes `some` by reference, and it's mutable. Can call mutable methods
|
||||||
|
// or use it in mutable operations
|
||||||
|
fun do_something(&Something some) -> Bool {}
|
||||||
|
do_something(&s1)
|
||||||
|
|
||||||
|
|
||||||
|
var arr1 = Array(10, 20, 30)
|
||||||
|
var arr2 = &arr1
|
||||||
|
|
||||||
|
|
||||||
|
Owned/Reference Mutable
|
||||||
|
Type Owned n
|
||||||
|
&Type Reference n
|
||||||
|
mut Type Owned y
|
||||||
|
&mut Type Reference y
|
||||||
|
|
||||||
|
|
||||||
|
Copy/Reference Mutable Equivalent
|
||||||
|
Some Copy n 1 (technically) references the other data
|
||||||
|
&Some Reference n 1 References the other data
|
||||||
|
mut Some Copy y 2 Creates a __mutable__ copy
|
||||||
|
&mut Some Reference y 3 References the other data, __mutable__
|
||||||
|
|
||||||
|
|
||||||
|
## `Array[A]::map`
|
||||||
|
|
||||||
|
```thp
|
||||||
|
fun map[B](this, (A) -> B callback) -> Array[B]
|
||||||
|
```
|
||||||
|
|
||||||
|
Applies `callback` to all the elements of this array, and
|
||||||
|
returns those new values in a new array.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
```thp
|
||||||
|
val numbers = Array(1, 2, 3, 4, 5)
|
||||||
|
|
||||||
|
val numbers_squared = numbers.map {it ** 2}
|
||||||
|
|
||||||
|
print(numbers_squared) // Array(1, 4, 9, 16, 25)
|
||||||
|
|
||||||
|
numbers.map(fun(v) {
|
||||||
|
v - 2
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## `Array[A]::reduce`
|
||||||
|
|
||||||
|
```thp
|
||||||
|
fun reduce[B](
|
||||||
|
this,
|
||||||
|
B initial,
|
||||||
|
(A previous, B current) -> B callback,
|
||||||
|
) -> B
|
||||||
|
```
|
||||||
|
|
||||||
|
Iteratively reduce the array to a single value using `callback`.
|
||||||
|
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
```thp
|
||||||
|
val numbers = Array(1, 2, 3, 4, 5)
|
||||||
|
|
||||||
|
val sum = numbers.reduce(0, \+)
|
||||||
|
val sum = numbers.reduce(0) {$1 + $2}
|
||||||
|
val sum = numbers.reduce(0, fun(prev, curr) {prev + curr})
|
||||||
|
|
||||||
|
print(sum) // 15
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
```thp
|
||||||
|
val numbers = Array(1, 2, 3, 4, 5)
|
||||||
|
|
||||||
|
val sum = numbers.reduce("", fun(prev, curr) {prev + curr})
|
||||||
|
|
||||||
|
val sum = numbers.reduce("") {prev, curr -> prev + curr}
|
||||||
|
|
||||||
|
print(sum) // "12345"
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
```thp
|
||||||
|
// Functor
|
||||||
|
|
||||||
|
fun fmap(
|
||||||
|
(A) -> B,
|
||||||
|
f[A],
|
||||||
|
) -> f[B]
|
||||||
|
|
||||||
|
fun (<$)(
|
||||||
|
A,
|
||||||
|
f[B],
|
||||||
|
) -> f[A]
|
||||||
|
|
||||||
|
|
||||||
|
// Applicative
|
||||||
|
|
||||||
|
fun pure(A) -> f[A]
|
||||||
|
|
||||||
|
fun (<*>)(
|
||||||
|
f[A -> B],
|
||||||
|
f[A],
|
||||||
|
) -> f[B]
|
||||||
|
|
||||||
|
fun (*>)(
|
||||||
|
f[_],
|
||||||
|
f[B],
|
||||||
|
) -> f[B]
|
||||||
|
|
||||||
|
fun (<*)(
|
||||||
|
f[A],
|
||||||
|
f[_],
|
||||||
|
) -> f[A]
|
||||||
|
|
||||||
|
|
||||||
|
// Monad
|
||||||
|
|
||||||
|
fun (>>=)[m, A, B](
|
||||||
|
m[A],
|
||||||
|
(A) -> m[B],
|
||||||
|
) -> m[B]
|
||||||
|
|
||||||
|
|
||||||
|
(Array[Int], Int -> Array[String]) -> Array[String]
|
||||||
|
|
||||||
|
val result = Array(1, 2, 3, 4, 5) >>= {Array($.into[String]())}
|
||||||
|
|
||||||
|
print(result) // Array("1", "2", "3", "4", "5")
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
```thp
|
||||||
|
Option[Int] result = "322".try_into()
|
||||||
|
Option[Int] result_halved = result >>= {Some($ / 2)}
|
||||||
|
|
||||||
|
print(result_halved) // Some(161)
|
||||||
|
|
||||||
|
|
||||||
|
Option[Int] result = "abc".try_into()
|
||||||
|
Option[Int] result_halved = result >>= {Some($ / 2)}
|
||||||
|
|
||||||
|
print(result_halved) // None
|
||||||
|
```
|
||||||
|
|
||||||
|
```thp
|
||||||
|
fun (<$>)[m, A, B](
|
||||||
|
(A) -> B,
|
||||||
|
m[A],
|
||||||
|
) -> m[B]
|
||||||
|
|
||||||
|
|
||||||
|
fun half(Int x) -> Int {
|
||||||
|
x / 2
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Option[Int] result = "322".try_into()
|
||||||
|
Option[Int] result_halved = result <$> half
|
||||||
|
|
||||||
|
print(result_halved) // Some(161)
|
||||||
|
|
||||||
|
|
||||||
|
Option[Int] result = "abc".try_into()
|
||||||
|
Option[Int] result_halved = result <$> half
|
||||||
|
|
||||||
|
print(result_halved) // None
|
||||||
|
```
|
||||||
|
|
||||||
|
```thp
|
||||||
|
fun (>>)[A, B, C](
|
||||||
|
(A) -> B,
|
||||||
|
(B) -> C,
|
||||||
|
) -> (A) -> C
|
||||||
|
|
||||||
|
val f1 = add1 >> times2
|
||||||
|
|
||||||
|
f1(5) // 12
|
||||||
|
```
|
||||||
|
|
@ -4,6 +4,13 @@ Welcome to the documentation of the THP programming languague.
|
|||||||
|
|
||||||
THP is a new programming language that compiles to PHP.
|
THP is a new programming language that compiles to PHP.
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
This page discusses some of the design decitions of the language,
|
||||||
|
if you want to install THP go to the installation guide](/installation-guide)
|
||||||
|
|
||||||
|
If you want to learn the language, go to the learn section.
|
||||||
|
|
||||||
## Goals
|
## Goals
|
||||||
|
|
||||||
- Bring static typing to PHP: Not just type hints, not use `mixed` for everything
|
- Bring static typing to PHP: Not just type hints, not use `mixed` for everything
|
||||||
|
@ -4,3 +4,25 @@ has_index: true
|
|||||||
children:
|
children:
|
||||||
- path: index
|
- path: index
|
||||||
name: Index
|
name: Index
|
||||||
|
- path: install
|
||||||
|
name: Install
|
||||||
|
- path: basics
|
||||||
|
name: Basics
|
||||||
|
children:
|
||||||
|
- path: hello-world
|
||||||
|
name: Hello, world!
|
||||||
|
- path: datatypes
|
||||||
|
name: Datatypes
|
||||||
|
- path: the-compiler
|
||||||
|
name: The compiler
|
||||||
|
- name: Variables
|
||||||
|
path: variables
|
||||||
|
- path: io
|
||||||
|
name: Input & Output
|
||||||
|
- path: comments
|
||||||
|
name: Comments
|
||||||
|
- name: Flow control
|
||||||
|
path: flow-control
|
||||||
|
children:
|
||||||
|
- name: Conditionals
|
||||||
|
path: conditionals
|
||||||
|
10
md/learn/install.md
Normal file
10
md/learn/install.md
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
# Install
|
||||||
|
|
||||||
|
## From scratch
|
||||||
|
|
||||||
|
Also install php (through XAMPP in windows/mac, php in linux) and Composer.
|
||||||
|
|
||||||
|
## With composer
|
||||||
|
|
||||||
|
TBD, the user should be able to just run `composer require thp` and
|
||||||
|
the proper binary should be intalled.
|
403
pnpm-lock.yaml
403
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
@ -12,157 +12,71 @@
|
|||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Fira+Sans+Condensed:wght@400;500;600;700;800;900&family=Fugaz+One&family=Inconsolata&family=Inter&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Fira+Sans+Condensed:wght@400;500;600;700;800;900&family=Fugaz+One&family=Inconsolata&family=Inter&display=swap" rel="stylesheet">
|
||||||
|
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Fira+Code&family=Josefin+Sans:ital,wght@0,400;1,700&display=swap" rel="stylesheet">
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-c-bg text-c-text">
|
<body class="bg-c-bg text-c-text">
|
||||||
<div class="px-2 grid grid-cols-2 gap-4 relative">
|
|
||||||
<div class="text-center h-screen overflow-hidden sticky top-0 left-0">
|
|
||||||
|
|
||||||
<div class="rounded-md m-4 p-4 bg-c-primary"
|
<div
|
||||||
style="box-shadow: 0 0 10px -4px var(--c-box-shadow);"
|
class="max-w-[70rem] mx-auto py-28 grid grid-cols-2 gap-4"
|
||||||
>
|
>
|
||||||
<h1
|
<div>
|
||||||
class="py-8 font-display"
|
<h1 class="font-display font-bold italic text-[6rem] leading-tight">
|
||||||
style="font-size: 10rem; text-shadow: 3px 3px 0 var(--c-bg)"
|
Typed
|
||||||
>
|
<br>
|
||||||
thp 23
|
Hypertext
|
||||||
</h1>
|
<br>
|
||||||
<h1 class="text-6xl text-center py-8 font-display"
|
Processor
|
||||||
style="text-shadow: 1px 1px 0 var(--c-bg)"
|
</h1>
|
||||||
>
|
<p class="font-display text-3xl pt-4">
|
||||||
Typed Hypertext Processor
|
Syntax, stdlib and types for PHP
|
||||||
</h1>
|
</p>
|
||||||
|
|
||||||
<p class="text-2xl">
|
|
||||||
A <b>modern, consistent</b> typed language for PHP.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div class="m-4 relative mb-2 button-effect inline-block bg-c-bg rounded">
|
|
||||||
<button class="button-effect-receiver py-2 px-4 rounded font-display
|
|
||||||
bg-c-text text-c-primary"
|
|
||||||
>
|
|
||||||
Get started
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="m-4 relative mb-2 button-effect inline-block bg-c-bg rounded">
|
|
||||||
<a class="button-effect-receiver py-2 px-4 rounded font-display inline-block
|
|
||||||
bg-c-text text-c-primary"
|
|
||||||
href="/learn/"
|
|
||||||
>
|
|
||||||
Learn
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
|
<div
|
||||||
<div class="rounded-md my-4 mx-2 p-4 bg-c-primary"
|
class="bg-[var(--code-theme-bg-color)] p-8 rounded-lg"
|
||||||
style="box-shadow: 0 0 10px -4px var(--c-box-shadow);"
|
|
||||||
>
|
>
|
||||||
<h2 class="text-2xl mb-2">
|
<svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg>
|
||||||
A truly Static Type System
|
<br>
|
||||||
</h2>
|
|
||||||
<p>
|
|
||||||
thp keeps track of the datatype of all variables, and allows
|
|
||||||
you to have complex types and type inference.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<pre
|
<pre
|
||||||
class="p-2 my-2 rounded-md bg-c-bg language-misti"
|
class="rounded-md bg-c-bg language-misti"
|
||||||
style="box-shadow: inset 0 0 10px -5px var(--c-box-shadow);"
|
style="padding: 0 !important;"
|
||||||
>type <span class="token class-name">Person</span> = {
|
><span class="token keyword">use</span> <span class="token class-name">Globals</span>::<span class="token class-name">POST</span>
|
||||||
<span class="token class-name">String</span> name,
|
<span class="token keyword">use</span> <span class="token class-name">JSON</span>
|
||||||
<span class="token class-name">String</span> lastName,
|
|
||||||
<span class="token class-name">Int</span> age,
|
<span class="token keyword">val</span> person_id = <span class="token class-name">POST</span>::get(<span class="token string">"person_id"</span>) ?: <span class="token keyword">die</span>
|
||||||
|
|
||||||
|
<span class="token keyword">match</span> <span class="token class-name">Person</span>::find_by_id(person_id) {
|
||||||
|
<span class="token class-name">Ok</span>(person) => {
|
||||||
|
<span class="token class-name">JSON</span>::encode(person)
|
||||||
|
}
|
||||||
|
<span class="token class-name">Err</span>(e) => {
|
||||||
|
<span class="token class-name">JSON</span>::encode(Obj {<span class="token string">"error"</span>: e})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
</pre>
|
||||||
<span class="token class-name">Option</span>[<span class="token class-name">Array</span>[<span class="token class-name">Person</span>]] persons = <span class="token class-name">PersonManager</span>::getAll()
|
|
||||||
|
|
||||||
print(<span class="token string">"There are {persons?.length ?? 0} persons registered!"</span>)</pre>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="rounded-md my-4 mx-2 p-4 bg-c-primary"
|
|
||||||
style="box-shadow: 0 0 10px -4px var(--c-box-shadow);"
|
|
||||||
>
|
|
||||||
<h2 class="text-2xl mb-2">
|
|
||||||
A <b>new</b> stdlib for PHP
|
|
||||||
</h2>
|
|
||||||
<p>
|
|
||||||
thp groups all global variables and function of PHP into modules,
|
|
||||||
to allow easy access and organization.
|
|
||||||
<br>
|
|
||||||
Function names, parameters and return types are improved, and you
|
|
||||||
can treat primitive types as objects.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<pre
|
|
||||||
class="p-2 my-2 rounded-md bg-c-bg language-misti"
|
|
||||||
style="box-shadow: inset 0 0 10px -5px var(--c-box-shadow);"
|
|
||||||
><span class="token keyword">val</span> name = <span class="token string">"John Doe"</span>
|
|
||||||
|
|
||||||
<span class="token keyword">val</span> lastNamePos = name.indexOf(<span class="token string">"Doe"</span>) <span class="token comment">// Instead of `strpos`</span>
|
|
||||||
<span class="token keyword">val</span> letters = name.split(<span class="token string">""</span>) <span class="token comment">// Instead of `str_split` or `explode`</span>
|
|
||||||
|
|
||||||
<span class="token keyword">val</span> notALetters = letters.filter { $ != <span class="token string">"a"</span> } <span class="token comment">// Instead of `array_filter`</span></pre>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="rounded-md my-4 mx-2 p-4 bg-c-primary"
|
|
||||||
style="box-shadow: 0 0 10px -4px var(--c-box-shadow);"
|
|
||||||
>
|
|
||||||
<h2 class="text-2xl mb-2">
|
|
||||||
Sound null safety & Pattern Matching
|
|
||||||
</h2>
|
|
||||||
<p>
|
|
||||||
All null values must be explicitly marked and handled,
|
|
||||||
avoiding many errors, via the <code>Option</code> ADT.
|
|
||||||
<br>
|
|
||||||
<br>
|
|
||||||
Also, functions that return <code>false</code> as
|
|
||||||
an error state now return an <code>Option</code>,
|
|
||||||
and exceptions return a <code>Result</code> instead.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<pre
|
|
||||||
class="p-2 my-2 rounded-md bg-c-bg language-misti"
|
|
||||||
style="box-shadow: inset 0 0 10px -5px var(--c-box-shadow);"
|
|
||||||
><span class="token keyword">val</span> allowedColors = <span class="token class-name">Array</span>(<span class="token string">"red"</span>, <span class="token string">"blue"</span>, <span class="token string">"green"</span>)
|
|
||||||
|
|
||||||
<span class="token keyword">val</span> response = match colors.search(<span class="token string">"purple"</span>) {
|
|
||||||
<span class="token class-name">Some</span>(_) -> <span class="token string">"purple is allowed!"</span>
|
|
||||||
<span class="token class-name">None</span> -> <span class="token string">"purple is not allowed"</span>
|
|
||||||
}
|
|
||||||
|
|
||||||
print(response)</pre>
|
|
||||||
|
|
||||||
<pre
|
|
||||||
class="p-2 my-2 rounded-md bg-c-bg language-misti"
|
|
||||||
style="box-shadow: inset 0 0 10px -5px var(--c-box-shadow);"
|
|
||||||
>use <span class="token class-name">PDO</span>
|
|
||||||
use <span class="token class-name">Globals</span>::<span class="token class-name">Env</span>
|
|
||||||
|
|
||||||
<span class="token keyword">val</span> #(<span class="token class-name">Some</span>(dbUri), <span class="token class-name">Some</span>(dbUser), <span class="token class-name">Some</span>(dbPassword)) = #(
|
|
||||||
<span class="token class-name">Env</span>::get(<span class="token string">"DB_URI"</span>),
|
|
||||||
<span class="token class-name">Env</span>::get(<span class="token string">"DB_USERNAME"</span>),
|
|
||||||
<span class="token class-name">Env</span>::get(<span class="token string">"DB_PASSWORD"</span>),
|
|
||||||
)
|
|
||||||
else {
|
|
||||||
die(<span class="token string">"All 3 db environment variables must be set."</span>)
|
|
||||||
}
|
|
||||||
|
|
||||||
match <span class="token class-name">PDO</span>(dbUri, dbUser, dbPassword) {
|
|
||||||
<span class="token class-name">Ok</span>(connection) -> { /* db operations */ }
|
|
||||||
<span class="token class-name">Err</span>(pdoException) -> { /* handle exception */ }
|
|
||||||
}</pre>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="max-w-[70rem] mx-auto text-center"
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
class="inline-block font-display text-2xl border-4 border-[#F5A9B8] py-3 px-8 mx-6 rounded"
|
||||||
|
href="/learn/"
|
||||||
|
>
|
||||||
|
Learn
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a
|
||||||
|
class="inline-block font-display text-2xl border-4 border-[#5BCEFA] py-3 px-8 mx-6 rounded"
|
||||||
|
href="/install/"
|
||||||
|
>
|
||||||
|
Install
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
@ -13,16 +13,23 @@
|
|||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Fira+Sans+Condensed:wght@400;500;600;700;800;900&family=Fugaz+One&family=Inconsolata&family=Inter&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Fira+Sans+Condensed:wght@400;500;600;700;800;900&family=Fugaz+One&family=Inconsolata&family=Inter&display=swap" rel="stylesheet">
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Fira+Code&family=Josefin+Sans:ital,wght@0,400;1,700&display=swap" rel="stylesheet">
|
||||||
|
|
||||||
|
<style>
|
||||||
|
html {
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-c-bg text-c-text">
|
<body class="bg-c-bg text-c-text">
|
||||||
<div class="grid grid-cols-[10rem_12rem_auto] gap-2">
|
<div class="grid grid-cols-[10rem_12rem_auto] gap-2 max-w-[70rem] mx-auto">
|
||||||
<div class="p-2 overflow-x-scroll max-h-screen sticky top-0">
|
<div class="p-2 overflow-x-scroll max-h-screen sticky top-0">
|
||||||
<div class="relative mb-2 button-effect">
|
<div class="relative mb-2 button-effect">
|
||||||
<a class="button-effect-receiver inline-block w-[9rem] p-4 bg-c-primary rounded-md"
|
<a class="button-effect-receiver inline-block w-[9rem] p-4 bg-c-primary rounded-md"
|
||||||
href="/"
|
href="/"
|
||||||
>
|
>
|
||||||
<h1
|
<h1
|
||||||
class="py-8 font-display text-6xl text-center"
|
class="py-8 font-display text-6xl text-center font-bold italic"
|
||||||
style="text-shadow: 3px 3px 0 var(--c-bg)"
|
style="text-shadow: 3px 3px 0 var(--c-bg)"
|
||||||
>
|
>
|
||||||
thp
|
thp
|
||||||
@ -32,13 +39,13 @@
|
|||||||
<div class="w-full h-full bg-c-text absolute top-0 left-0 -z-10 rounded-md"></div>
|
<div class="w-full h-full bg-c-text absolute top-0 left-0 -z-10 rounded-md"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<nav class="rounded-md p-4 bg-c-primary">
|
<nav class="rounded-md p-4 border-2 border-[#F5A9B8]">
|
||||||
{{pages}}
|
{{pages}}
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="py-2 max-h-screen overflow-x-scroll sticky top-0">
|
<div class="py-2 max-h-screen overflow-x-scroll sticky top-0">
|
||||||
<nav class="rounded-md p-4 bg-c-secondary">
|
<nav class="rounded-md p-4 border-2 border-[#5BCEFA]">
|
||||||
<h2 class="text-2xl">On this page</h2>
|
<h2 class="text-2xl">On this page</h2>
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
@ -46,7 +53,7 @@
|
|||||||
{{sidebar}}
|
{{sidebar}}
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<main class="markdown p-4 my-2">
|
<main class="markdown p-4 my-2">
|
||||||
{{markdown}}
|
{{markdown}}
|
||||||
</main>
|
</main>
|
||||||
|
@ -16,9 +16,10 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
fontFamily: {
|
fontFamily: {
|
||||||
"mono": ["Inconsolata", "Iosevka", "monospace"],
|
"mono": ["'Fira Code'", "Inconsolata", "Iosevka", "monospace"],
|
||||||
"display": ["'Fugaz One'", "Inter", "'Fira Sans Condensed'", "sans-serif"],
|
"display": ["'Josefin Sans'", "'Fugaz One'", "sans-serif"],
|
||||||
"body": ["'Fira Sans Condensed'", "Inter", "sans-serif"],
|
"body": ["'Fira Sans Condensed'", "Inter", "sans-serif"],
|
||||||
|
"nav-title": ["'Josefin Sans'", "'Fugaz One'", "sans-serif"],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
plugins: [],
|
plugins: [],
|
||||||
|
@ -33,7 +33,7 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pre, code {
|
pre, code {
|
||||||
font-family: Inconsolata, monospace;
|
font-family: 'Fira Code', Inconsolata, monospace;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button-effect-receiver {
|
.button-effect-receiver {
|
||||||
@ -44,6 +44,9 @@ pre, code {
|
|||||||
transform: translateX(-3px) translateY(-3px);
|
transform: translateX(-3px) translateY(-3px);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.markdown p {
|
||||||
|
margin: 0.75rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Used by headers generated from markdown */
|
/* Used by headers generated from markdown */
|
||||||
.heading-linked :hover::after{
|
.heading-linked :hover::after{
|
||||||
|
Loading…
Reference in New Issue
Block a user