fix: adding in standard build

This commit is contained in:
D. Moonfire 2022-10-13 09:00:21 -05:00
parent f1c6706bcb
commit c31ada3643
26 changed files with 17227 additions and 6415 deletions

View File

@ -6,12 +6,21 @@ root = true
[*]
charset = utf-8
end_of_line = lf
indent_brace_style = K&R
indent_size = 4
indent_style = space
insert_final_newline = true
max_line_length = 120
max_line_length = 80
tab_width = 4
trim_trailing_whitespace = true
curly_bracket_next_line = true
[*.{js,ts}]
quote_type = double
[*.yaml]
indent_size = 4
tab_width = 4
indent_style = space
[package.json]
indent_size = 2
tab_width = 2

2
.envrc Normal file
View File

@ -0,0 +1,2 @@
export PATH=$PWD/scripts:$PWD/node_modules/.bin:$PATH
use flake || use nix

18
.gitignore vendored
View File

@ -1,11 +1,13 @@
*~
build/
tmp/
node_modules/
.direnv/
tmp/
build/
# Output
*-*.*.*.epub
*-*.*.*.pdf
*-*.*.*.mobi
*-*.*.*.html
*-*.*.*.docx
.*-swp
dmoonfire*.pdf
dmoonfire*.docx
dmoonfire*.html
dmoonfire*.mobi
dmoonfire*.epub
*.bz2

17
.prettierignore Normal file
View File

@ -0,0 +1,17 @@
CHANGELOG.md
package-lock.json
yarn.lock
*~
archives/
build/
extras/
others/
node_modules/
submissions/
sample-edits/
maps/
.direnv/
tmp/
edit/

36
.woodpecker.yml Normal file
View File

@ -0,0 +1,36 @@
clone:
git:
image: woodpeckerci/plugin-git
settings:
tags: true
pipeline:
build:
image: registry.gitlab.com/dmoonfire/nix-flake-docker:latest
commands:
- nix profile install 'nixpkgs#fontconfig'
- nix develop --command scripts/build.sh
secrets:
- gitea_token
- s3_bucket
- s3_endpoint
- s3_access_key_id
- s3_secret_access_key
when:
event: [push, pull_request, tag]
tag: v*
release:
image: registry.gitlab.com/dmoonfire/nix-flake-docker:latest
commands:
- nix profile install 'nixpkgs#fontconfig'
- nix develop --command scripts/release.sh
secrets:
- gitea_token
- s3_bucket
- s3_endpoint
- s3_access_key_id
- s3_secret_access_key
when:
event: push
branch: main

6
commitlint.config.js Normal file
View File

@ -0,0 +1,6 @@
module.exports = {
extends: ["@commitlint/config-conventional"],
rules: {
"body-max-line-length": [0],
},
};

View File

@ -4,24 +4,32 @@
"character": {
"pov": 100,
"name": "Rutejìmo",
"character_slug": "rutejimo",
"color": "hsl(45, 40%, 50%)"
},
"source": {
"pov": 100,
"volume": 0,
"title": "Sand and Blood",
"status": "stable",
"word_count": 69263,
"length": "Novel",
"title_slug": "sand-and-blood",
"identifier_slug": "0100-00-sand-and-blood",
"copyright_year": 2020,
"status": "Stable",
"genres": [
"Action",
"Drama"
],
"has_dedication": false,
"git": {
"http_url": "https://gitlab.com/fedran/sand-and-blood.git",
"http_url": "https://src.mfgames.com/fedran-sources/sand-and-blood.git",
"branch": "master"
},
"links": {
"development": {
"git": "https://gitlab.com/fedran/sand-and-blood"
"git": "https://src.mfgames.com/fedran-sources/sand-and-blood/",
"issues": "https://src.mfgames.com/fedran-sources/sand-and-blood/issues"
},
"online": {
"wattpad": "https://www.wattpad.com/story/46671031-sand-and-blood",
@ -36,6 +44,198 @@
"amazon": "http://amzn.to/2FKsMSb",
"typewriter": "https://store.typewriter.press/product/sand-and-blood/"
}
}
},
"cover": {
"cover_slug": "0100-00-sand-and-blood",
"title_page_lines": [
"Sand and",
"Blood"
]
},
"warnings": {
"text": "This novel contains no scenes of sexual assault."
},
"chapters": [
{
"title": "Rutejìmo",
"word_count": 1519,
"date": "2012-02-18",
"summary": "Rutejìmo was on top of the clan's shrine roof trying to sneak in and steal his grandfather's ashes. It was a teenage game, but also one to prove that he was capable of becoming an adult. He ended up falling off the roof.\nThe shrine guard, Hyonèku, caught him before he hurt himself. After a few humiliating comments, he gave Rutejìmo a choice: tell the clan elder or tell his grandmother. Neither choice was good, but Rutejìmo decided to tell his grandmother.\n"
},
{
"title": "Confession",
"word_count": 2150,
"date": "2012-02-19",
"summary": "Rutejìmo returned to his grandmother's cave. He tried to sneak around, but she caught him entering. When she asked what he had done, he told her that he had been up at the shrine. His grandmother got upset and began to berate and beat him, chasing him out of the cave.\nGemènyo interrupted her beating to ask if it was justified. When Tejíko explained the reason, he agreed but she had lost her anger. As she went back into the cave, Gemènyo sat down with Rutejìmo and asked questions. The discussion came to the upcoming rite of passage and how Rutejìmo would gain magical powers once he experienced it. Gemènyo wouldn't give details about the rite, but he did tell Rutejìmo that magic wouldn't change him.\nRutejìmo snapped back, saying that Gemènyo wasn't the greatest warrior in the clan. Gemènyo didn't seem bothered, but suggested that if Rutejìmo wanted to be the best, he needed to do something. Rutejìmo agreed, even knowing he wouldn't.\n"
},
{
"title": "Morning",
"word_count": 2914,
"date": "2012-02-26",
"summary": "Rutejìmo was sent out to get breakfast for his grandparents. Along the way to the valley floor, he got distracted by Mapábyo, Hyonèku's adopted daughter, riding on top of Opōgyo, one of the clan's mechanical dogs used for dragging heavy loads around. They talk for a short while before she asked him to come with her to take the load up to her father, who is at the lookout above the valley entrance.\nEven though Hyonèku had caught him the night before, Rutejìmo agreed. When they get there, Hyonèku started to read a naughty letter from his wife before Gemènyo interrupted him. Embarrassed, Hyonèku focused on his daughter while Gemènyo talked with Rutejìmo more.\nAs they are speaking, runners from the clan arrive. The lead runner is Desòchu, Rutejìmo's brother. Rutejìmo ran down to meet him.\n"
},
{
"title": "Rivals",
"word_count": 1176,
"date": "2012-03-04",
"summary": "When Rutejìmo tried to deliver breakfast to his grandparents, he is accosted by Karawàbi and Tsubàyo, two teenagers who bullied him frequently. Both of them forced Rutejìmo to spill the bowls of food, but Desòchu caught them before they hit the ground. Coming back, he gave the two bullies a lecture and sent them off. And then he told Rutejìmo not to get revenge. Rutejìmo promised, even though he planned on doing so anyways.\n"
},
{
"title": "Decisions",
"word_count": 2574,
"date": "2012-04-17",
"summary": "After dinner, Rutejìmo found out that all the adults were gathering in the shrine to make a decision. He decided to use that time for revenge on Karawàbi and Tsubàyo. But, as he went to leave, Gemènyo caught him and told him that it was important that he didn't try. Something serious was about to happen. And then he ran to the shrine.\nRutejìmo decided to eavesdrop on the shrine event. He crawled on top and listened at the opening. Inside, they announced that Chimípu's mother had died and they were sending Chimípu on her rite of passage to accept her as an elder of the clan. As they spoke, Rutejìmo realized that she was kneeling next to him; he didn't hear her coming.\nAfter everyone agreed on Chimípu, the clan elder asked about the other teenagers. As the votes came in, it was clear that Tsubàyo, Karawàbi, and Pidòhu would be included. The last vote was Rutejìmo, who almost didn't get accepted except for his grandfather insisting that he was ready.\n"
},
{
"title": "Heading Out",
"word_count": 1620,
"date": "2012-04-18",
"summary": "Tejíko told Rutejìmo that she knew he had been listening to the vote. After promising to beat him more, she sent him to get ready and leave. He did, excited about the trip. On the way to the village entrance, he spotted Chimípu running but he couldn't run faster than her. He also encountered Pidòhu, a weak teenager who spent most of his time alone. Pidòhu made some observations that the trip had been planned for months and that there were a lot of adults coming along for a \"simple\" rite of passage for one woman. Rutejìmo dismissed Pidòhu's comments.\n"
},
{
"title": "Middle of the Trip",
"word_count": 1508,
"date": "2012-04-25",
"summary": "Many days later, Rutejìmo continued to struggle with keeping up with the clan. They all ran across the desert, in the sun, and the effort exhausted him. He was the slowest except for Pidòhu. Desòchu didn't help Rutejìmo, but he did help Pidòhu which invoked some jealousy in Rutejìmo.\nAs they arrived at a set of Wind's Teeth, a set of tall rocks sticking out of the ground, Desòchu suggested that Rutejìmo help Pidòhu. The last person to enter camp did most of the work setting it up. Rutejìmo didn't help, but Chimípu did. Chimípu had not been struggling with the run and kept up with the elders easily.\n"
},
{
"title": "The Morning Sun",
"word_count": 3060,
"date": "2012-05-04",
"summary": "Rutejìmo is woken up by Chimípu when she found out that all of the adults had abandoned the teenagers in the middle of the night. Only Rutejìmo, Chimípu, Karawàbi, Tsubàyo, and Pidòhu were left behind. After some fighting, Chimípu ran off to look for the elders and left the others behind. Tsubàyo took charge and began to order Pidòhu and Rutejìmo to get breakfast and find food.\nThe adults had taken the supplies except for a bag hanging from a tall cliff. Tsubàyo made Pidòhu climb the rock to get it. Rutejìmo wanted to help, but didn't have the courage to speak up. As Pidòhu struggled with the rocks, Karawàbi started to throw rocks at Pidòhu to Tsubàyo's amusement. Rutejìmo struggled with his emotions.\nOne of the rocks hit Pidòhu and he fell, breaking his leg.\n"
},
{
"title": "Blood and Bone",
"word_count": 2935,
"date": "2012-06-22",
"summary": "As Pidòhu cried out in pain, Tsubàyo refused to help him. Rutejìmo froze, unable to do anything. He kept looking at Tsubàyo to take charge, but the other teenager turned his back on Pidòhu and ran off.\nChimípu came back to find the damage. She lashed out at Rutejìmo, calling him a coward. Later, she went after Tsubàyo and Karawàbi, but came back bruised and angry.\nShe gave Rutejìmo a choice to go with Tsubàyo and Karawàbi, who were packing to head home, or stay. With her anger toward him, Rutejìmo joined the others and left Chimípu and Pidòhu.\n"
},
{
"title": "Separation Anxiety",
"word_count": 1466,
"date": "2012-06-22",
"summary": "Tsubàyo, Karawàbi, and Rutejìmo ran toward home. Rutejìmo fell behind and the other two didn't help him. Instead, he struggled until he saw a bird that only appeared if he ran fast enough. It was enough to keep him going and he found that he could run faster, fast enough to catch up with the others. When neither Tsubàyo or Karawàbi could see the bird, Rutejìmo realized it was the clan spirit, Shimusògo.\n"
},
{
"title": "Standing Alone",
"word_count": 1953,
"date": "2012-08-23",
"summary": "At the end of the day, they reached a rock shelter for the night. Neither Tsubàyo or Karawàbi had any intend in helping set up and they ordered Rutejìmo to serve them. It was the same behavior that the two had treated Pidòhu before they left.\n"
},
{
"title": "Investigating the Night",
"word_count": 2408,
"date": "2012-08-25",
"summary": "Rutejìmo set up the camp and cooked food for the other two teenagers. Tsubàyo and Karawàbi also left the cleaning to him. As it grew dark, they noticed campfires in the distance. Tsubàyo was curious and decided to investigate. Karawàbi remained behind, but Tsubàyo made Rutejìmo come along.\nOnce they got closer, they saw it was a caravan with some strange brass item. The caravan had a small herd of black horses and Tsubàyo decided to steal some. Rutejìmo refused, claiming that the Shimusògo's power came from running, not riding. They argued before deciding to go their separate ways.\nRutejìmo turned and headed back toward their shelter, thought it was impossible to find in the darkness.\n"
},
{
"title": "Breaking Up",
"word_count": 2900,
"date": "2012-08-25",
"summary": "Rutejìmo woke up in the desert, alone and helpless. He didn't know where to go, so he walked blindly until he realized that the bird would appear if he ran. He accelerated and then followed the clan spirit back to the camp.\nAt the camp, Karawàbi demanded that Rutejìmo make him breakfast. Rutejìmo realized that he couldn't remain with him and started to pack up to return to Chimípu and Pidòhu. Karawàbi realized that and attacked Rutejìmo. It was a short fight until Rutejìmo managed to slam a tent spike into Karawàbi's foot before running away.\n"
},
{
"title": "Coming Back",
"word_count": 1751,
"date": "2012-08-26",
"summary": "Rutejìmo returned to the Wind's Teeth. Pidòhu was happy to see him, but Chimípu was furious. She berated him for leaving until Rutejìmo offered his throat, to give her a choice to kill him or let him stay. Chimípu saved him and sullenly let her help.\nRutejìmo got to see the damage done to Pidòhu, it was a compound fracture. When Chimípu ran off to find some help, Pidòhu helped Rutejìmo change his bandage.\n"
},
{
"title": "A Quiet Conversation",
"word_count": 1074,
"date": "2012-08-27",
"summary": "Rutejìmo and Pidòhu talked in the middle of the night about the nature of magic, the struggles of growing up, and how the rites of passage work. Pidòhu reveals that Chimípu had already manifested her powers before the rites. It happened after her mother died and before they made the vote to start the rite of passage. The rite was to accept her into the clan, even if the spirit had already done so.\n"
},
{
"title": "Pushing Forward",
"word_count": 1862,
"date": "2012-09-06",
"summary": "Pidòhu started to hallucinate from his injuries. Knowing that he was going to die in the desert, he begged Rutejìmo to take him home. Rutejìmo agreed. Chimípu returned from getting supplies and demanded to know what was going on. Pidòhu negotiated his case and she agreed. They made a makeshift stretcher to pull him along and decided to take turns pulling him across the sand.\n"
},
{
"title": "An Evening Run",
"word_count": 2314,
"date": "2012-09-08",
"summary": "Finding shelter for the night, Chimípu made sure Pidòhu was safe and then asked Rutejìmo on a run. They ran together for some distance and then stopped, talking about what was going on. She revealed some details about Rutejìmo's brother. Then she taught him how to fire rocks at high speed using their speed magic.\n"
},
{
"title": "Quiet-Voiced Threat",
"word_count": 2204,
"date": "2012-09-08",
"summary": "Rutejìmo sat on guard while the others slept. He struggled with his fear of darkness and his own feelings of inadequacy. He also wondered what had changed between him and Chimípu, it felt like she had became a sudden friend with their shared experiences of chasing Shimusògo and learning how to fire rocks at each other.\nWhile he was thinking, he heard a noise. At first, he was worried but then assumed it was his imagination. But then he was surprised when a woman pressed a knife to his throat. He lost control of his bladder, but was helpless to do anything.\nChimípu woke up and attacked the intruder, Mikáryo. They fought in the darkness until Mikáryo finally pinned Chimípu to the ground. When the older woman realized that Chimípu, Pidòhu, and Rutejìmo were all teenagers, she relaxed. She claimed she was looking for the Shimusogo who killed her sister and stole her horse. When they figured out it was Tsubàyo that killed her, Mikáryo threatened to take his soul with an unnamed blade.\nMikáryo gave them three nights to deliver Tsubàyo or she would kill one of them. She disappeared into the night, leaving the three alone.\n"
},
{
"title": "Humiliated",
"word_count": 2320,
"date": "2012-09-09",
"summary": "Rutejìmo woke up still humiliated by his actions from the night before when Mikáryo attacked. For the first time, he wanted to run, so he ran off until he felt better. He managed to move fast enough he came up to another stopping point where he spotted signs of the other Shimusògo.\nWhen he got back, he and Pidòhu spoke about the nature of Chimípu becoming a warrior. Rutejìmo didn't know about the consequences including sterility, inability to marry, and an almost guaranteed death in battle.\nPidòhu also confided that he will never become a Shimusògo. Instead, he kept seeing a giant shadow sailing across the desert and thought that it was his path.\nChimípu came back and Rutejìmo offered a knife to replace the one that was ruined during the fight with Mikáryo. Chimípu accepted it.\n"
},
{
"title": "Shimusogo Karawàbi",
"word_count": 1553,
"date": "2012-09-09",
"summary": "Fueled by his humiliation and guilt when he couldn't fight Mikáryo, Rutejìmo took the weight of Pidòhu's stretcher on himself. When Chimípu tried to take her turn, he refused.\nThey planned on stopping at the same rocky outcropping that Rutejìmo attacked Karawàbi. When they got there, they found vultures circling over the camp and Karawàbi sitting in a pool of blood with his throat cut.\nAt first, they thought Mikáryo had killed Karawàbi, but Mikáryo used a different weapon. Rutejìmo got sick seeing the violence.\nThey took the remaining supplies and left in a hurry.\n"
},
{
"title": "From the Shadows",
"word_count": 3771,
"date": "2012-09-17",
"summary": "Haunted by the sight of Karawàbi's death, Rutejìmo continued to draw Pidòhu along the desert. He couldn't figure out who did it.\nChimípu joined him and asked if he would help her prepare for the night. He agreed and helped change Pidòhu's bandage. It got worse, but it also gave Pidòhu a chance to ask Rutejìmo about why he refused to let Chimípu pull the stretcher. Rutejìmo tried to explain how he was too weak: too weak to fight Mikáryo, too weak to match his brother, to weak for anything else.\nWhen Rutejìmo realized he had bared his soul, Pidòhu pushed him and Chimípu to go on a run. They did and then talked to each other, each one talking about their fears and personal struggles.\nThey were interrupted by Tsubàyo who continued to ride Mikáryo's sister's horse. He spoke of hearing the horses and demonstrated powers of the horse clan. Tsubàyo also pointed out that he could travel through shadows, faster than Chimípu or Rutejìmo could run.\nFinally, Chimípu attacked but Tsubàyo disappeared into the shadows. Chimípu screamed like a bird, the powers of her magic growing, before she passed out. When she recovered, they ran back to Pidòhu.\n"
},
{
"title": "Shadows from Sunlight",
"word_count": 1743,
"date": "2012-09-18",
"summary": "Chimípu woke Rutejìmo up and insisted they move. It quickly became apparent that the encounter with Tsubàyo worried her. She struggled with her inability to defeat Tsubàyo.\nPidòhu suggested that Chimípu ran and she did. When she was gone, Pidòhu asked Rutejìmo about running and clan powers. He revealed that he thought the shadows he saw were actually a spirit, Tateshyúso, and showed how he could use it to shade Rutejìmo from the sun and keep him cool.\nChimípu joined them and they continued along the way as Pidòhu practiced summoning Tateshyúso and shading them.\n"
},
{
"title": "One Mistake",
"word_count": 2881,
"date": "2012-09-19",
"summary": "After eight hours of dragging Pidòhu across the desert, Rutejìmo was able to help Pidòhu with using his powers.\nChimípu on the other hand had gone ahead and was using her powers to set up the camp. She was still obviously nervous and afraid of Tsubàyo. When Pidòhu called her out on it, she snapped back. He insisted she ran and, reluctantly, she did.\nWhen she came back, Rutejìmo went on a run himself. It was a long run where he realized and tested his powers. But, when he came back, the camp had been destroyed. Chimípu had been knocked out and Tsubàyo had kidnapped Pidòhu.\nChimípu recovered and burst into rage, but she struggled between her desire to rescue Pidòhu and remained behind to protected Rutejìmo. Rutejìmo insisted she go after Pidòhu and he would remain at the camp.\n"
},
{
"title": "Alone in the Dark",
"word_count": 2050,
"date": "2012-09-19",
"summary": "Rutejìmo sat alone in the dark, staring at a small fire. He was afraid of the dark. He also mulled over various struggles in his head.\nAs he was thinking, Mikáryo showed up. She brought meat and roasted it over Rutejìmo's flame. They talked about Chimípu abandoning Rutejìmo in the dark and the dangers of being alone.\nMikáryo also talked about Tsubàyo. He was in the process of becoming a Pabinkúe. She no longer was content to have one of their lives, she would only accept taking Tsubàyo back into her clan.\nWhen it gets late, Mikáryo tells Rutejìmo to go to sleep. He resisted, but she promised he would wake up in the morning.\n"
},
{
"title": "Lessons Taught",
"word_count": 2282,
"date": "2012-09-20",
"summary": "Rutejìmo woke up to Mikáryo's cooking. He asked why she protected him. She told him that she watched over him because he was \"pathetic.\" She also told him that Chimípu had returned in the night.\nHe went to wake her, but she was already up. She apologized because she wasn't able to save Pidòhu. After a few short words, he left to answer nature and found that Mikáryo had killed a giant snake that would have attacked him. Mikáryo came back and chipped off a tooth, telling him to wear it until he figured out his position in life.\nThey returned to the fire and talked to Chimípu. Mikáryo insisted that Chimípu go after Pidòhu, but take Rutejìmo with her. She told them were Tsubàyo would be and gave Chimípu her fighting weapon.\n"
},
{
"title": "Preparing for Battle",
"word_count": 1519,
"date": "2012-09-22",
"summary": "They came up to where Tsubàyo had taken Pidòhu, a large arch. Chimípu was prepared to take Tsubàyo by herself, but Rutejìmo insisted on helping. After a short discussion, including Chimípu revealing that she intensely disliked Mikáryo, she agreed to let him help.\nThey plan their attack.\n"
},
{
"title": "Pabinkue Tsubàyo",
"word_count": 3006,
"date": "2012-10-13",
"summary": "The attack against Tsubàyo. As Chimípu charged, Rutejìmo supported by firing makeshift shots against him and his horses. Rutejìmo missed, but one of the misses came near Chimípu who plucked the shot, accelerated it, and threw it at Tsubàyo. A horse jumped to shield him, but the explosion threw them apart.\nAs Chimípu and Tsubàyo fought, Rutejìmo saw a chance to rescue Pidòhu. He ran over and was relieved to find Pidòhu was glad to see him. However, one of Tsubàyo's horses stepped out of the shadows and attacked Rutejìmo. Tsubàyo joined in and almost killed Rutejìmo, but Chimípu's fireball caught him and they were fighting.\nIn the chaos, Rutejìmo ended up fighting Tsubàyo as Chimípu rescued Pidòhu. In the end, Tsubàyo knocked Rutejìmo out with a horse kick.\n"
},
{
"title": "The Offer",
"word_count": 2090,
"date": "2012-10-17",
"summary": "Rutejìmo woke up. Tsubàyo had bound him for delivering to Mikáryo. He was in pain, with cracked bones and struggling to breathe.\nAs they waited, Tsubàyo talked about gaining his powers, how it felt and his abilities.\nWhen Mikáryo arrives, Tsubàyo offered Rutejìmo's life to her. Mikáryo made a show of looking at Rutejìmo, but then checked on him before turning him down. She told Tsubàyo that she waited for him and that he would be coming with her. He refused.\n"
},
{
"title": "Rescue",
"word_count": 7345,
"date": "2012-10-18",
"summary": "Rutejìmo had to wait until sunrise before anything else happened. The wait was torture because of his broken bones and concussion. When it did, it came with a windstorm that had a shape of Tateshyúso.\nIt ended up being a brutal fight with Chimípu attacking Tsubàyo with speed and fire, Tsubàyo using the shadows and his horses, and Pidòhu using wind powers.\nAt one point, Pidòhu falls from a stone arch but this time Rutejìmo caught him.\nWhen the fight ended, the rest of the Shimusògo elders arrived. With Tsubàyo alone, they were about to kill him but then Mikáryo arrived to claim him. There was about to be a fight, but then Rutejìmo stopped it by asking for a vote. After a moment of stunned silence, they did with the decision to allow Mikáryo and Tsubàyo to leave winning by a small margin.\nHowever, Desòchu and Chimípu asked for closure from Mikáryo who granted it. They beat Tsubàyo. Rutejìmo couldn't watch and ran away before they finished.\n"
},
{
"title": "A Year Later",
"word_count": 1315,
"date": "2012-10-19",
"summary": "One year later, Rutejìmo is watching the rest of the clan celebrate the birth of Shimusògo. He saw on the shrine, not wanting to participate, but then Hyonèku and Gemènyo join him with a bottle of wine to give him grief about acting like an old man.\nRutejìmo finally got the answer of who killed Karawàbi, his brother. Instead of being upset, he understood why the death was important. He asked how close he was to being killed also and they told him they had already decided to do so but then he returned to Chimípu before they could do it.\nGemènyo noticed that Mapábyo was trying to sneak into the shrine. Hyonèku started to get his daughter, but then Rutejìmo did.\n"
}
]
}
}

58
flake.lock Normal file
View File

@ -0,0 +1,58 @@
{
"nodes": {
"flake-utils": {
"locked": {
"lastModified": 1642700792,
"narHash": "sha256-XqHrk7hFb+zBvRg6Ghl+AZDq03ov6OshJLiSWOoX5es=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "846b2ae0fc4cc943637d3d1def4454213e203cba",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1643805626,
"narHash": "sha256-AXLDVMG+UaAGsGSpOtQHPIKB+IZ0KSd9WS77aanGzgc=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "554d2d8aa25b6e583575459c297ec23750adb6cb",
"type": "github"
},
"original": {
"id": "nixpkgs",
"ref": "nixos-unstable",
"type": "indirect"
}
},
"nixstable": {
"locked": {
"lastModified": 1622516815,
"narHash": "sha256-ZjBd81a6J3TwtlBr3rHsZspYUwT9OdhDk+a/SgSEf7I=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "7e9b0dff974c89e070da1ad85713ff3c20b0ca97",
"type": "github"
},
"original": {
"id": "nixpkgs",
"ref": "21.05",
"type": "indirect"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs",
"nixstable": "nixstable"
}
}
},
"root": "root",
"version": 7
}

28
flake.nix Normal file
View File

@ -0,0 +1,28 @@
{
inputs = {
nixstable.url = "nixpkgs/21.05";
nixpkgs.url = "nixpkgs/nixos-unstable";
flake-utils.url = "github:numtide/flake-utils";
};
outputs = { self, nixpkgs, nixstable, flake-utils }:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = nixpkgs.legacyPackages.${system};
stable = nixstable.legacyPackages.${system};
in {
devShell = pkgs.mkShell {
buildInputs = [
pkgs.epubcheck
pkgs.nixfmt
pkgs.nodejs-16_x
pkgs.pandoc
pkgs.pdftk
pkgs.python39Full
pkgs.python39Packages.weasyprint
pkgs.jq
pkgs.s3cmd
];
};
});
}

11
matter/about.md Normal file
View File

@ -0,0 +1,11 @@
---
title: About D. Moonfire
---
D. Moonfire is the remarkable intersection of a computer nerd and a scientist. He inherited a desire for learning, endless curiosity, and a talent for being a polymath from both of his parents. Instead of focusing on a single genre, he writes stories and novels in many different settings ranging from fantasy to science fiction. He also throws in the occasional romance or forensics murder mystery to mix things up.
In addition to having a borderline unhealthy obsession with the written word, he is also a developer who loves to code as much as he loves writing.
He lives near Cedar Rapids, Iowa with his wife, numerous pet computers, and a pair of highly mobile things of the male variety.
You can see more work by D. Moonfire at his website at [https://d.moonfire.us/](https://d.moonfire.us/). His fantasy world, Fedran, can be found at [https://fedran.com/](https://fedran.com/).

13
matter/fedran.md Normal file
View File

@ -0,0 +1,13 @@
---
title: Fedran
---
Fedran is a world caught on the cusp of two great ages.
For centuries, the Crystal Age shaped society through the exploration of magic. Every creature had the ability to affect the world using talents and spells. The only limitation was imagination, will, and the inescapable rules of resonance. But as society grew more civilized, magic became less reliable and weaker.
When an unexpected epiphany seemingly breaks the laws of resonance, everything changed. Artifacts no longer exploded when exposed to spells, but only if they were wrapped in cocoons of steel and brass. The humble fire rune becomes the fuel for new devices, ones powered by steam and pressure. These machines herald the birth of a new age, the Industrial Age.
Now, the powers of the old age struggle against the onslaught of new technologies and an alien way of approaching magic. Either the world will adapt or it will be washed away in the relentless march of innovation.
To explore the world of Fedran, check out [https://fedran.com/](https://fedran.com/). There you'll find stories, novels, character write-ups and more.

27
matter/legal.md Normal file
View File

@ -0,0 +1,27 @@
---
title: Legal
---
Copyright © 2020 D. Moonfire\
Some Rights Reserved\
Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International
Cover art by D. Moonfire
All characters, events, and locations are fictitious. Any resemblance to persons, past, present, and future is coincidental and highly unlikely.
This novel contains no scenes of sexual assault.
Broken Typewriter Press\
5001 1st Ave SE\
Ste 105 #243\
Cedar Rapids, IA 52402
Broken Typewriter Press\
[https://broken.typewriter.press/](https://broken.typewriter.press/)
{% if (edition.isbn) %}
ISBN {{edition.isbn}}
{% endif %}
Version {{edition.version}}

32
matter/license.md Normal file
View File

@ -0,0 +1,32 @@
---
title: License
---
This book is distributed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International license. More info can be found at [https://creativecommons.org/licenses/by-nc-sa/4.0/](https://creativecommons.org/licenses/by-nc-sa/4.0/). This means:
### You are free to:
- Share — copy and redistribute the material in any medium or format
- Adapt — remix, transform, and build upon the material
The licensor cannot revoke these freedoms as long as you follow the license terms.
### Under the following terms:
- Attribution — You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use.
- NonCommercial — You may not use the material for commercial purposes.
- ShareAlike — If you remix, transform, or build upon the material, you must distribute your contributions under the same license as the original.
No additional restrictions — You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits.
### Preferred Attribution
The preferred attribution for this novel is:
> "Sand and Blood" by D. Moonfire is licensed under CC BY-NC-SA 4.0
In the above attribution, use the following links:
- Flight of the Scions: [https://fedran.com/sand-and-blood/](https://fedran.com/sand-and-blood/)
- D. Moonfire: https://d.moonfire.us/
- CC BY-NC-SA 4.0: https://creativecommons.org/licenses/by-nc-sa/4.0/

1
matter/pad.html Normal file
View File

@ -0,0 +1 @@
<br />

14
matter/title.html Normal file
View File

@ -0,0 +1,14 @@
---
title: Title
---
<div class="title">
<div class="title-area">
<div class="large">Sand and</div>
<div class="large">Blood</div>
</div>
<div class="author">D. Moonfire</div>
<div class="publisher">Broken Typewriter Press &#8226; Cedar Rapids</div>
</div>

22730
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,86 +1,50 @@
{
"name": "sand-and-blood",
"version": "3.1.0",
"fedran": {
"pov": "0100",
"vol": "00"
"private": true,
"description": "\"Sand and Blood\" is a novel by D. Moonfire.",
"author": {
"name": "D. Moonfire"
},
"description": "A novel by D. Moonfire",
"author": "D. Moonfire",
"license": "CC-BY-NC-SA-4.0",
"repository": {
"type": "git",
"url": "git+https://gitlab.com/fedran/sand-and-blood.git"
"url": "git+https://src.mfgames.com/fedran-sources/sand-and-blood.git"
},
"homepage": "https://fedran.com/sand-and-blood/",
"scripts": {
"build:pdf": "mfgames-writing-format build pdf",
"build:epub": "mfgames-writing-format build epub",
"build": "npm run build:epub && npm run build:mobi && npm run build:pdf",
"build:extended": "npm run build && npm run build:html && npm run build:docx",
"build:docx": "sed 's@&#173;@@g' < dmoonfire-$npm_package_fedran_pov-$npm_package_fedran_vol-$npm_package_name-$npm_package_version.html | pandoc -f html -t docx -o dmoonfire-$npm_package_fedran_pov-$npm_package_fedran_vol-$npm_package_name-$npm_package_version.docx",
"build:mobi": "kindlegen dmoonfire-$npm_package_fedran_pov-$npm_package_fedran_vol-$npm_package_name-$npm_package_version.epub",
"build:html": "mfgames-writing-format build html",
"prebuild:mobi": "npm run build:epub",
"prebuild": "rm -f $npm_package_name-*.* $npm_package_name.tar.bz2",
"bundle": "tar -cjf $npm_package_name.tar.bz2 *.epub *.pdf",
"prebundle": "npm run build",
"upload": "aws --endpoint-url https://$AWS_ENDPOINT s3 cp --acl public-read $npm_package_name.tar.bz2 s3://$AWS_BUCKET/$npm_package_name.tar.bz2",
"preupload": "npm run bundle"
"build:docx": "mfgames-writing-format build docx",
"build": "run-s build:*",
"prepare": "husky install"
},
"dependencies": {
"@fedran/writing-hyphen": "^1.0.0",
"@fedran/writing-theme": "^3.0.5",
"@mfgames-writing/epub2": "^1.1.3",
"@mfgames-writing/format": "^2.0.0",
"@fedran/writing-theme": "^4.0.2",
"@mfgames-writing/contracts": "^4.4.0",
"@mfgames-writing/docx-format": "^1.0.2",
"@mfgames-writing/epub2-format": "^2.1.1",
"@mfgames-writing/format": "^3.3.1",
"@mfgames-writing/guillemet": "^1.0.0",
"@mfgames-writing/html": "^0.1.1",
"@mfgames-writing/hyphen": "^0.4.3",
"@mfgames-writing/weasyprint": "^4.0.0"
"@mfgames-writing/hyphen-pipeline": "^1.0.2",
"@mfgames-writing/liquid-theme": "^2.1.1",
"@mfgames-writing/weasyprint-format": "^5.0.4",
"markdown-it-multimd-table": "^4.1.3"
},
"devDependencies": {
"@commitlint/cli": "^7.6.1",
"@commitlint/config-conventional": "^7.6.0",
"@semantic-release/changelog": "^3.0.6",
"@semantic-release/git": "^7.0.18",
"commitizen": "^2.10.1",
"cz-conventional-changelog": "^2.1.0",
"husky": "^0.14.3",
"semantic-release": "^15.14.0"
},
"release": {
"branch": "master",
"message": "chore(release): v${nextRelease.version}\n\n${nextRelease.notes}",
"verifyConditions": [
"@semantic-release/changelog",
"@semantic-release/git"
],
"analyzeCommits": [
"@semantic-release/commit-analyzer"
],
"prepare": [
"@semantic-release/changelog",
"@semantic-release/npm",
"@semantic-release/git"
],
"publish": [],
"success": [],
"fail": []
},
"commitlint": {
"extends": [
"@commitlint/config-conventional"
]
},
"config": {
"commitizen": {
"path": "./node_modules/cz-conventional-changelog"
}
},
"husky": {
"hooks": {
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
}
},
"private": true
"@commitlint/cli": "^15.0.0",
"@commitlint/config-conventional": "^15.0.0",
"@saithodev/semantic-release-gitea": "^2.1.0",
"@semantic-release/changelog": "^6.0.1",
"@semantic-release/exec": "^6.0.3",
"@semantic-release/git": "^10.0.1",
"@semantic-release/npm": "^8.0.3",
"@semantic-release/release-notes-generator": "^10.0.3",
"husky": "^7.0.2",
"markdowny": "^0.2.1",
"npm-run-all": "^4.1.5",
"prettier": "^2.0.5",
"semantic-release": "^18.0.1"
}
}

123
publication.json Normal file
View File

@ -0,0 +1,123 @@
{
"metadata": {
"title": "{{edition.fedran.source.title}}",
"author": "D. Moonfire",
"language": "en",
"theme": "@fedran/writing-theme",
"outputDirectory": ".",
"outputFilename": "dmoonfire-{{edition.fedran.source.title_slug}}-{{edition.name}}-{{edition.version}}.{{edition.ext}}",
"markdown": {
"extensions": [
{
"package": "markdown-it-multimd-table",
"options": {
"headerless": true
}
}
]
},
"style": {
"css": "td { width: 6em; } td[colspan=\"2\"] { width: 12em; }"
}
},
"includes": [
{
"json": "./fedran.json",
"merge": "metadata.fedran"
}
],
"editions": {
"epub": {
"format": "@mfgames-writing/epub2-format",
"ext": "epub"
},
"pdf": {
"format": "@mfgames-writing/weasyprint-format",
"isbn": "",
"images": {
"grayscale": true,
"opaque": true
},
"ext": "pdf"
},
"docx": {
"format": "@mfgames-writing/docx-format",
"ext": "docx"
}
},
"contents": [
{
"element": "cover",
"source": "build/fedran-covers/pov/covers/0100-00-sand-and-blood.jpg",
"linear": false,
"exclude": {
"editions": ["pdf"],
"toc": true
}
},
{
"element": "bastard",
"source": "matter/title.html",
"linear": false,
"exclude": {
"editions": ["epub", "html"],
"toc": true
}
},
{
"element": "title",
"source": "matter/title.html",
"linear": false,
"exclude": {
"toc": true
}
},
{
"element": "legal",
"source": "matter/legal.md",
"liquid": true,
"linear": false
},
{
"element": "toc",
"linear": false,
"title": "Contents",
"exclude": {
"editions": ["pdf"]
}
},
{
"element": "chapter",
"number": 1,
"directory": "chapters",
"source": "/^chapter-\\d+.(markdown|md)$/",
"start": true,
"page": 1,
"pipeline": [
{
"module": "@mfgames-writing/guillemet"
},
{
"module": "@fedran/writing-hyphen"
},
{
"module": "@mfgames-writing/hyphen-pipeline",
"exclude": ["`.*?`", "<code>.*?</code>"]
}
]
},
{
"element": "appendix",
"source": "matter/about.md"
},
{
"element": "appendix",
"source": "matter/fedran.md"
},
{
"element": "appendix",
"id": "license",
"source": "matter/license.md"
}
]
}

39
release.config.js Normal file
View File

@ -0,0 +1,39 @@
module.exports = {
branches: ["main"],
extends: ["@commitlint/config-conventional"],
message:
"chore(release): v${nextRelease.version} [skip ci]\n\n${nextRelease.notes}",
plugins: [
[
"@semantic-release/commit-analyzer",
{
preset: "conventionalcommits",
},
],
"@semantic-release/release-notes-generator",
"@semantic-release/npm",
[
"@semantic-release/exec",
{
prepareCmd: "npm run build",
},
],
"@semantic-release/changelog",
"@semantic-release/git",
[
"@saithodev/semantic-release-gitea",
{
giteaUrl: "https://src.mfgames.com",
assets: [
{ path: "*.epub", label: "EPUB2", type: "other" },
{ path: "*.pdf", label: "PDF", type: "other" },
{ path: "*.docx", label: "DOCX", type: "other" },
],
},
],
],
};

18
scripts/build.sh Executable file
View File

@ -0,0 +1,18 @@
#!/usr/bin/env bash
# Set up logging.
log() { echo "🛠️ $(basename $0): $@"; }
# Move into the root folder.
cd $(dirname $(dirname $0))
# Make sure everything is set up.
log "setting up project"
./scripts/setup.sh || exit 1
# Build the project outputs.
log "building PDF"
npm run build:pdf || exit 1
log "building EPUB"
npm run build:epub || exit 1

27
scripts/check-env-bucket.sh Executable file
View File

@ -0,0 +1,27 @@
#!/usr/bin/env bash
# Checks the environment to see if we have all the requisite components needed
# to upload or download from the S3 bucket.
# Set up logging.
log() { echo "⚗️ $(basename $0): $@"; }
# Move into the root folder.
cd $(dirname $(dirname $0))
for i in S3_ACCESS_KEY_ID S3_SECRET_ACCESS_KEY S3_ENDPOINT S3_BUCKET
do
if [ "x${!i}" = "x" ]
then
log "missing environment variable $i"
exit 1
fi
done
if [ ! which s3cmd 2> /dev/null ]
then
log "cannot find 's3cmd' to execute"
exit 1
fi
exit 0

40
scripts/release.sh Executable file
View File

@ -0,0 +1,40 @@
#!/usr/bin/env bash
# Builds the final versions of the book and then upload the results to various
# locations.
# Set up logging.
log() { echo "️🚢 $(basename $0): $@"; }
# Move into the root folder.
cd $(dirname $(dirname $0))
# Perform the basic environment checks and setup.
./scripts/setup.sh || exit 1
./scripts/check-env-bucket.sh || exit 1
# Clean up old versions of the file.
log "cleaning up prior versions which may not match versions"
rm -f dmoonfire*
# Perform the release process.
log "performing semantic release"
export GIT_CREDENTIALS="dmoonfire:$GITEA_TOKEN"
npx semantic-release || exit 1
# Create a tarball of the output files and upload them to S3.
if ls dmoonfire* &> /dev/null
then
log "packaging output into a tarball"
tar -cjf sand-and-blood.tar.bz2 dmoonfire*
log "uploading tarball to bucket"
export AWS_ACCESS_KEY_ID=$S3_ACCESS_KEY_ID
export AWS_SECRET_ACCESS_KEY=$S3_SECRET_ACCESS_KEY
export AWS_ENDPOINT=$S3_ENDPOINT
export AWS_BUCKET=$S3_BUCKET
s3cmd --access_key=$S3_ACCESS_KEY_ID --access_token=$S3_SECRET_ACCESS_KEY --host=$S3_ENDPOINT --host-bucket=$S3_ENDPOINT -P put sand-and-blood.tar.bz2 s3://$S3_BUCKET || exit 1
else
log "no files to upload"
fi

31
scripts/setup-fedran-covers.sh Executable file
View File

@ -0,0 +1,31 @@
#!/usr/bin/env bash
# Download the Fedran covers for inclusion. This places everything into the
# ./build/fedran-covers folder.
# Set up logging.
log() { echo "🖼 $(basename $0): $@"; }
# Move into the root folder.
cd $(dirname $(dirname $0))
# Check to see if it is already downloaded.
if [ -d ./build/fedran-covers ]
then
log "fedran-covers already exists, not downloading"
else
# Make sure we have all the required environment variables.
log "fedran-covers is missing, download from bucket"
./scripts/check-env-bucket.sh || exit 1
# Set the variables.
export AWS_ACCESS_KEY_ID=$S3_ACCESS_KEY_ID
export AWS_SECRET_ACCESS_KEY=$S3_SECRET_ACCESS_KEY
export AWS_ENDPOINT=$S3_ENDPOINT
export AWS_BUCKET=$S3_BUCKET
# Download and extract the bucket.
mkdir -p ./build/fedran-covers
s3cmd --access_key=$S3_ACCESS_KEY_ID --access_token=$S3_SECRET_ACCESS_KEY --host=$S3_ENDPOINT --host-bucket=$S3_ENDPOINT -P get s3://$S3_BUCKET/fedran-covers.tar.bz2 ./build/fedran-covers/fedran-covers.tar.bz2 || exit 1
tar x -C build/fedran-covers -f build/fedran-covers/fedran-covers.tar.bz2
fi

24
scripts/setup-fonts.sh Executable file
View File

@ -0,0 +1,24 @@
#!/usr/bin/env bash
# Sets up the fonts for building the PDF output. It doesn't do it if we are not
# in a CI environment.
# Set up logging.
log() { echo "✒️ $(basename $0): $@"; }
# Move into the root directory.
cd $(dirname $(dirname $0))
# We only insert the fonts if we are on a CI server.
if [ "x$CI" == "x" ]
then
log "not in CI environment, not installing fonts"
else
log "installing fonts"
mkdir -p ~/.local/share/fonts
cp $(nix-build --no-out-link '<nixpkgs>' -A source-serif-pro)/share/fonts/opentype/*.otf ~/.local/share/fonts
cp $(nix-build --no-out-link '<nixpkgs>' -A source-sans-pro)/share/fonts/opentype/*.otf ~/.local/share/fonts
log "updating font caches"
fc-cache
fi

17
scripts/setup-node.sh Executable file
View File

@ -0,0 +1,17 @@
#!/usr/bin/env bash
# Installs the required Node packages
# Set up logging.
log() { echo "📦️ $(basename $0): $@"; }
# Move into the root directory.
cd $(dirname $(dirname $0))
if [ -d ./node_modules ]
then
log "node_modules already exists"
else
log "setting up node"
npm install --ci
fi

9
scripts/setup.sh Executable file
View File

@ -0,0 +1,9 @@
#!/usr/bin/env bash
# Move into the root folder.
cd $(dirname $(dirname $0))
# Run the setup commands.
./scripts/setup-fonts.sh || exit 1
./scripts/setup-fedran-covers.sh || exit 1
./scripts/setup-node.sh || exit 1