kashi
Version:
Singing at the top of my lungs
217 lines (155 loc) β’ 9.41 kB
Markdown
<div align="center">
<a href="https://gitlab.com/lucasmc64/kashi">GitLab</a> β’
<a href="https://www.npmjs.com/package/kashi">NPM</a> β’
<a href="https://unpkg.com/browse/kashi@latest">CDN</a> β’
<a href="https://ko-fi.com/lucasmc64">Ko-fi</a>
</div>

# π€ Kashi
## π― Goal
This project is a dependency-free library that aims to provide a way to correctly read, format, structure, and display song lyrics.
## π Features
- [x] π΅ Process and list song lyrics in .lrc files
- [x] πͺ Supports both directly inputting the .lrc file and a URL that returns it
- [x] βοΈ Implements the Observer pattern and emits events at each step of the process whenever something changes
- [x] βοΈ Allows you to enter custom text when the lyrics line is empty
- [ ] π€ Synchronizes the lyrics with the music that is playing
- [ ] π© Supports multiple lyrics for the same song (useful to keep track of the original lyrics and their translation)
- [ ] π§ Supports the [Walaoke extension](https://en.wikipedia.org/wiki/LRC_(file_format)#Walaoke_extension)
- [ ] ποΈ Supports the [A2 extension](https://en.wikipedia.org/wiki/LRC_(file_format)#A2_extension_(Enhanced_LRC_format))
## π¨ How to use it in my project?
### <span id="classic-scripts">π Classic scripts</span>
The project is also exported using [UMD](https://github.com/umdjs/umd), which means that all variables and classes such as the `Kashi` class is exposed globally, and can be used in any script imported after the library.
> **Note**: You should **change `X.Y.Z` to the library version number** according to your needs, this is just an example. It is recommended to always use the latest version.
>
> It is recommended that you pin to the latest stable version of the lib. However, if you always want to use the latest version, you can also use `latest` instead of a predefined version number. **Be careful** though, breaking changes may be introduced and your project may need to adapt to the changes.
```html
<!DOCTYPE html>
<html>
<head>
<!-- ... -->
<script src="https://unpkg.com/kashi@X.Y.Z/kashi.js" defer></script>
<!-- ... -->
</head>
<body>
<div id="kashi"></div>
</body>
</html>
```
```js
"use strict";
// Using the file or using a url, both works fine
new Kashi({
// url, // Public link that returns the file when a GET request is made OR...
file. // Loaded from an input[type="file"] or anywhere else
container: document.getElementById("kashi"),
});
```
### π¦οΈ ES6 Modules
The HTML is very similar to the classic scripts version, just change the `.js` extension to `.mjs` (and maybe will be necessary to adds a `type="module"` too), which will result in something similar to this:
> **Note**: Please read the [previous section](#classic-scripts) to get the details involved in importing and choosing a package version, they are the same here.
```html
<script
src="https://unpkg.com/kashi@X.Y.Z/kashi.mjs"
type="module"
defer
></script>
```
```javascript
import { Kashi } from "kashi";
// Usage is essentially the same as in the previous section
// Using the file or using a url, both works fine
new Kashi({
// url, // Public link that returns the file when a GET request is made OR...
file. // Loaded from an input[type="file"] or anywhere else
container: document.getElementById("kashi"),
});
```
### βοΈ React
Install the lib using your favorite package manager.
```bash
npm install kashi
```
Since the library was designed primarily to be used with vanilla JS, a _helper_ component needs to be created to encapsulate Kashi's behavior and make it simple to reuse throughout the application.
> **Note**: There is TypeScript support, and even if your project doesn't use the JS superset, it should help VSCode and other editors provide autocomplete/code suggestions.
```tsx
import { useEffect, useRef } from "react";
import { Kashi, KashiProps } from "kashi";
// Example using Vite, React and TypeScript
export const KashiWrapper = (props: KashiProps) => {
const ref = useRef<HTMLDivElement>(null);
useEffect(() => {
if (ref.current) {
new Kashi({
...props,
container: ref.current,
});
}
return () => {
// Required to avoid duplication when React is in Strict Mode
if (ref.current) {
ref.current.innerHTML = "";
}
};
}, [ref.current]);
return <div className="kashi-wrapper" ref={ref} />;
};
```
## π§ Constructor properties
You must pass some properties to Kashi to define what lyrics display and where. Here are its specifications:
| Property | Type | Default value | Is required? | Description |
| --------------- | ------------------ | ------------- | ------------ | ----------------------------------------- |
| `file` | `Blob` (or `File`) | - | No | Lyrics file |
| `url` | `string` | - | No | Lyrics url |
| `container` | `HTMLDivElement` | - | Yes | Element where the lyrics will be inserted |
| `emptyLineText` | `string` | `π` | No | Custom text for empty lines of the lyrics |
> Neither `file` nor `url` are βmandatoryβ, but **at least one of these properties must be specified**, otherwise an error will be thrown.
## πΎ Generated HTML structure
The `div#kashi` represents the `container` passed to `Kashi` where the song lyrics will be inserted.
Each line of lyrics present in the lrc file will be wrapped by a `<p></p>` tag and inserted into the `container`.
Here's an example:
```html
<div id="kashi">
<!-- ... -->
<p>Binkusu no sake wo todoke ni yuku yo</p>
<p>Umikaze kimakase namimakase</p>
<p>Shio no mukou de yuuhi mo sawagu</p>
<p>Sora nya wa wo kaku tori no uta</p>
<!-- ... -->
</div>
```
## π Methods and attributes
The instance generated by `Kashi` has some public methods and attributes that can be used to query or change properties on the fly.
| Name | Type | Description |
| ------------------ | --------- | ------------------------------------------------------------ |
| `url` | Attribute | Returns the url from the current lyrics if it was fetched from a link |
| `file` | Attribute | Returns the file from the current lyrics |
| `emptyLineText` | Attribute | Returns the default text set for empty lines |
| `setUrl` | Method | Function capable of changing the current lyrics file by passing the **url** of the new file |
| `setFile` | Method | Function capable of changing the current lyrics file by passing the the new **file** |
| `setEmptyLineText` | Method | Function capable of changing the text defined for empty lines |
| `subscribe` | Method | Function capable of defining a callback to be executed when a given event is triggered |
| `unsubscribe` | Method | Function capable of making a callback to stop listening to an event |
| `notify` | Method | Function capable of triggering an event |
## πΎ Events
When creating a new instance using `Kashi` you will have access to the `subscribe`, `unsubscribe` and `notify` methods, these methods can be used respectively to listen for an event, stop listening for an event and manually trigger an event. Below is the list of events triggered internally:
| Event | Data | Trigger |
| ------------------- | --------------------------- | ------------------------------------------------------------ |
| `urlSet` | `{ url: string }` | When instantiating by informing `url` or calling the `setUrl` method |
| `fileSet` | `{ file: Blob }` | When instantiating or calling the `setFile` method (when calling the `setUrl` method the file will be fetched and the `setFile` method called) |
| `emptyLineTextSet` | `{ emptyLineText: string }` | When instantiating by informing `emptyLineText` or calling the `setEmptyLineText` method |
| `lyricLinesUpdated` | `{ lyricLines: string[] }` | When inserting/updating lyrics in HTML |
## π€ How do I run the project on my machine?
The first step is to clone the project, either via terminal or even by downloading the compressed file (.zip). After that, go ahead.
### π οΈ Requirements
- [NodeJS and NPM](https://nodejs.org)
### β¨ Running the project
With the dependencies properly installed, still in the terminal, run `npm start`.
Create a simple demo project using vanilla HTML/JS and use the files in the `dist` folder for testing.
You can also create a demo project using React and use [npm link](https://docs.npmjs.com/cli/v9/commands/npm-link).
### π If everything went well...
Now you are running the project beautifully!
## βοΈ License
This project is under the GPL v3 license. See the [LICENSE](https://gitlab.com/lucasmc64/kashi/-/blob/main/LICENSE) for more information.
---
Made with π by lucasmc64 π [Get in touch!](https://www.linkedin.com/in/lucasmc64/)