Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • TransFem-org/sfm-js
  • dakkar/sfm-js
  • septicake/sfm-js-docs
3 results
Show changes
Commits on Source (164)
Showing with 4448 additions and 5700 deletions
......@@ -4,3 +4,5 @@ node_modules
/.eslintrc.js
/jest.config.ts
parser.js
/test
/test-d
module.exports = {
root: true,
parser: '@typescript-eslint/parser',
parserOptions: {
tsconfigRootDir: __dirname,
project: ['./tsconfig.json'],
},
plugins: [
'@typescript-eslint',
],
......@@ -11,22 +15,49 @@ module.exports = {
rules: {
'indent': ['error', 'tab', {
'SwitchCase': 1,
'MemberExpression': 'off',
'flatTernaryExpressions': true,
'ArrayExpression': 'first',
'ObjectExpression': 'first',
}],
'eol-last': ['error', 'always'],
'semi': ['error', 'always'],
'quotes': ['error', 'single'],
'comma-dangle': ['error', 'always-multiline'],
'keyword-spacing': ['error', {
'before': true,
'after': true,
}],
'key-spacing': ['error', {
'beforeColon': false,
'afterColon': true,
}],
'space-infix-ops': ['error'],
'space-before-blocks': ['error', 'always'],
'object-curly-spacing': ['error', 'always'],
'nonblock-statement-body-position': ['error', 'beside'],
'eqeqeq': ['error', 'always', { 'null': 'ignore' }],
'no-multiple-empty-lines': ['error', { 'max': 1 }],
'no-multi-spaces': ['error'],
'no-var': ['error'],
'prefer-arrow-callback': ['error'],
'no-throw-literal': ['error'],
'no-param-reassign': ['warn'],
'no-constant-condition': ['warn'],
'no-constant-condition': ['warn', {
checkLoops: false,
}],
'no-empty-pattern': ['warn'],
'@typescript-eslint/no-unnecessary-condition': ['warn', {
allowConstantLoopConditions: true,
}],
'@typescript-eslint/no-inferrable-types': ['warn'],
'@typescript-eslint/no-non-null-assertion': ['warn'],
'@typescript-eslint/explicit-function-return-type': ['warn'],
'@typescript-eslint/no-misused-promises': ['error', {
'checksVoidReturn': false,
}],
'@typescript-eslint/no-unused-vars': ['error', {
"argsIgnorePattern": "^_",
}]
},
};
name: Test
on: [push, pull_request]
jobs:
test:
runs-on: docker
steps:
- name: Checkout
uses: actions/checkout@v4.1.1
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20.5.1
- name: Install dependencies
run: npm i
- name: Build
run: npm run build
- name: Test
run: npm test
env:
CI: true
<!-- ℹ お読みください
PRありがとうございます! PRを作成する前に、以下をご確認ください:
- 可能であればタイトルに、以下で示すようなPRの種類が分かるキーワードをプリフィクスしてください。
- fix / refactor / feat / enhance / perf / chore
- また、PRの粒度が適切であることを確認してください。ひとつのPRに複数の種類の変更や関心を含めることは避けてください。
- このPRによって解決されるIssueがある場合は、そのIssueへの参照を本文内に含めてください。
- CHANGELOG.mdに変更点を追記してください。リファクタリングなど、利用者に影響を与えない変更についてはこの限りではありません。
- この変更により新たに作成、もしくは更新すべきドキュメントがないか確認してください。
- 機能追加やバグ修正をした場合は、可能であればテストケースを追加してください。
- テスト、Lintが通っていることを予め確認してください。
- `npm run test``npm run lint`でぞれぞれ実施可能です
- `npm run api`を実行してAPIレポートを更新し、差分がある場合はコミットしてください。
ご協力ありがとうございます🤗
-->
<!-- ℹ README
Thank you for your PR! Before creating a PR, please check the following:
- If possible, prefix the title with a keyword that identifies the type of this PR, as shown below.
- fix / refactor / feat / enhance / perf / chore
- Also, make sure that the granularity of this PR is appropriate. Please do not include more than one type of change or interest in a single PR.
- If there is an Issue which will be resolved by this PR, please include a reference to the Issue in the text.
- Please add the summary of the changes to CHANGELOG.md. However, this is not necessary for changes that do not affect the users, such as refactoring.
- Check if there are any documents that need to be created or updated due to this change.
- If you have added a feature or fixed a bug, please add a test case if possible.
- Please make sure that tests and Lint are passed in advance.
- You can run it with `npm run test` and `npm run lint`.
- Run `npm run api` to update the API report and commit it if there are any diffs.
Thanks for your cooperation 🤗
-->
# What
<!-- このPRで何をしたのか? どう変わるのか? -->
<!-- What did you do with this PR? How will it change things? -->
# Why
<!-- なぜそうするのか? どういう意図なのか? 何が困っているのか? -->
<!-- Why do you do it? What are your intentions? What is the problem? -->
# Additional info (optional)
<!-- テスト観点など -->
<!-- Test perspective, etc -->
name: API report
on: [push, pull_request]
jobs:
report:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup Node.js
uses: actions/setup-node@v1
with:
node-version: 16.5.0
- name: Cache dependencies
uses: actions/cache@v2
with:
path: ~/.npm
key: npm-${{ hashFiles('package-lock.json') }}
restore-keys: npm-
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: Check files
run: ls built
- name: API report
run: npm run api-prod
- name: Show report
if: always()
run: cat temp/mfm-js.api.md
name: Lint
on: [push, pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup Node.js
uses: actions/setup-node@v1
with:
node-version: 16.5.0
- name: Cache dependencies
uses: actions/cache@v2
with:
path: ~/.npm
key: npm-${{ hashFiles('package-lock.json') }}
restore-keys: npm-
- name: Install dependencies
run: npm ci
- name: Lint
run: npm run lint
# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
name: Test and coverage
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16.5.0]
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: Cache dependencies
uses: actions/cache@v2
with:
path: ~/.npm
key: npm-${{ hashFiles('package-lock.json') }}
restore-keys: npm-
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: Test
run: npm test
env:
CI: true
- name: Upload Coverage
uses: codecov/codecov-action@v1
image: node:latest
stages:
- testing
- deploy
test:
stage: testing
script:
- npm i
- npm run build
- npm run test
publish-npm:
stage: deploy
needs: ['test']
rules:
- if: $CI_COMMIT_BRANCH == "stable"
changes:
paths:
- package.json
script:
- echo "@transfem-org:registry=https://${CI_SERVER_HOST}/api/v4/projects/2/packages/npm/" > .npmrc
- echo "//${CI_SERVER_HOST}/api/v4/projects/2/packages/npm/:_authToken=${CI_JOB_TOKEN}" >> .npmrc
- npm i
- npm run build
- npm publish
<!--
## 0.x.x (unreleased)
### Features
### Improvements
### Changes
### Bugfixes
-->
## 0.24.0
### Features
- Supports Unicode 15.0 emoji
## 0.23.3
- tweak fn parsing
- fnNameList option removed
- emojiCodeList option removed
## 0.23.2
### Features
- Supports whitelisting of emoji code names. (#130)
## 0.23.1
### Improvements
- improve emoji code parsing
## 0.23.0
### Features
- Add Plain syntax (#101)
### Improvements
- The parser is now implemented in TypeScript! 🎉 (#92)
- Disable all syntax when nesting limited (#90)
### Changes
- Rename existing plain series (#113):
- parsePlain -> parseSimple
- MfmPlainNode -> MfmSimpleNode
### Bugfixes
- Fix a bug that allows line breaks in link label (#115)
## 0.22.1
### Improvements
- Removes a unnecessary built file
## 0.22.0
### Features
- Unicode emoji supports Unicode 14.0 emoji (#109)
### Improvements
- `()` pair is available on outside the hashtag (#111)
- Changes specs the center tag and strike (#108, 100fb0b)
- Improves link label parsing (#107)
### Bugfixes
- If there is a `[]` pair before the link, it will be mistakenly recognized as a part of link label. (#104)
## 0.21.0
### Features
- Supports nestLimit option. (#87, #91)
### Improvements
- Improve generation of brackets property of url node.
### Bugfixes
- Fix the Link node of the enclosed in `<>`. (#84)
- Fix parsing of the link label.
## 0.20.0
### Features
- Add tag syntaxes of bold `<b></b>` and strikethrough `<s></s>`. (#76)
- Supports whitelisting of MFM function names. (#77)
### Improvements
- Mentions in the link label are parsed as text. (#66)
- Add a property to the URL node indicating whether it was enclosed in `<>`. (#69)
- Disallows `<` and `>` in hashtags. (#74)
- Improves security.
### Changes
- Abolished MFM function v1 syntax. (#79)
## 0.19.0
### Improvements
- Ignores a blank line after quote lines. (#61)
## 0.18.0
### Improvements
- Twemoji v13.1 is supported.
## 0.17.0
### Improvements
- Improves syntax of inline code.
- Improves syntax of url.
- Improves syntax of hashtag.
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
syuilotan@yahoo.co.jp.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.
# Contribution guide
**[✨ English version available](/docs/CONTRIBUTING.en.md)**
プロジェクトに興味を持っていただきありがとうございます!
このドキュメントでは、プロジェクトに貢献する際に必要な情報をまとめています。
## 実装をする前に
機能追加やバグ修正をしたいときは、まずIssueなどで設計、方針をレビューしてもらいましょう(無い場合は作ってください)。このステップがないと、せっかく実装してもPRがマージされない可能性が高くなります。
また、実装に取り掛かるときは当該Issueに自分をアサインしてください(自分でできない場合は他メンバーに自分をアサインしてもらうようお願いしてください)。
自分が実装するという意思表示をすることで、作業がバッティングするのを防ぎます。
## Issues
Issueを作成する前に、以下をご確認ください:
- 重複を防ぐため、既に同様の内容のIssueが作成されていないか検索してから新しいIssueを作ってください。
- Issueを質問に使わないでください。
- Issueは、要望、提案、問題の報告にのみ使用してください。
- 質問は、[Misskey Forum](https://forum.misskey.io/)[Discord](https://discord.gg/Wp8gVStHW3)でお願いします。
## PRの作成
PRを作成する前に、以下をご確認ください:
- 可能であればタイトルに、以下で示すようなPRの種類が分かるキーワードをプリフィクスしてください。
- fix / refactor / feat / enhance / perf / chore 等
- また、PRの粒度が適切であることを確認してください。ひとつのPRに複数の種類の変更や関心を含めることは避けてください。
- このPRによって解決されるIssueがある場合は、そのIssueへの参照を本文内に含めてください。
- [`CHANGELOG.md`](/CHANGELOG.md)に変更点を追記してください。リファクタリングなど、利用者に影響を与えない変更についてはこの限りではありません。
- この変更により新たに作成、もしくは更新すべきドキュメントがないか確認してください。
- 機能追加やバグ修正をした場合は、可能であればテストケースを追加してください。
- テスト、Lintが通っていることを予め確認してください。
- `npm run test``npm run lint`でぞれぞれ実施可能です
- `npm run api`を実行してAPIレポートを更新し、差分がある場合はコミットしてください。
- APIレポートの詳細については[こちら](#api-extractor)
ご協力ありがとうございます🤗
## Tools
### eslint
このプロジェクトではコードのフォーマットチェック/整形に[eslint](https://eslint.org/)を導入しています。
CI上でも自動でチェックされ、ルールに則っていないコードがあるとエラーになります。
### Jest
このプロジェクトではテストフレームワークとして[Jest](https://jestjs.io/)を導入しています。
テストは[`/test`ディレクトリ](/test)に置かれます。
テストはCIにより各コミット/各PRに対して自動で実施されます。
ローカル環境でテストを実施するには、`npm run test`を実行してください。
### tsd
このプロジェクトでは型のテストを行うために[tsd](https://github.com/SamVerschueren/tsd)を導入しています。
Jestによるテストでは「型が期待したものか」というのはチェックすることができません。tsdを使うことで、型が意図したものであることを担保することができます。
tsdによる型テストは[`/test-d`ディレクトリ](/test-d)に置かれます。
テストはCIにより各コミット/各PRに対して自動で実施されます。
ローカル環境でテストを実施するには、`npm run test`を実行してください。
### API Extractor
このプロジェクトでは[API Extractor](https://api-extractor.com/)を導入しています。API ExtractorはAPIレポートを生成する役割を持ちます。
APIレポートはいわばAPIのスナップショットで、このライブラリが外部に公開(export)している各種関数や型の定義が含まれています。`npm run api`コマンドを実行すると、その時点でのレポートが[`/etc`ディレクトリ](/etc)に生成されるようになっています。
exportしているAPIに変更があると、当然生成されるレポートの内容も変わるので、例えばdevelopブランチで生成されたレポートとPRのブランチで生成されたレポートを比較することで、意図しない破壊的変更の検出や、破壊的変更の影響確認に用いることができます。
また、各コミットや各PRで実行されるCI内部では、都度APIレポートを生成して既存のレポートと差分が無いかチェックしています。もし差分があるとエラーになります。
PRを作る際は、`npm run api`コマンドを実行してAPIレポートを生成し、差分がある場合はコミットしてください。
レポートをコミットすることでその破壊的変更が意図したものであると示すことができるほか、上述したようにレポート間の差分が出ることで影響範囲をレビューしやすくなります。
### Codecov
このプロジェクトではカバレッジの計測に[Codecov](https://about.codecov.io/)を導入しています。カバレッジは、コードがどれくらいテストでカバーされているかを表すものです。
カバレッジ計測はCIで自動的に行われ、特に操作は必要ありません。カバレッジは[ここ](https://codecov.io/gh/misskey-dev/mfm.js)から見ることができます。
また、各PRに対してもそのブランチのカバレッジが自動的に計算され、マージ先のカバレッジとの差分を含んだレポートがCodecovのbotによりコメントされます。これにより、そのPRをマージすることでどれくらいカバレッジが増加するのか/減少するのかを確認することができます。
## レビュイーの心得
[PRのセクション](#PRの作成)をご一読ください。
また、後述の「レビュー観点」も意識してみてください。
## レビュワーの心得
- 直して欲しい点だけでなく、良い点も積極的にコメントしましょう。
- 貢献するモチベーションアップに繋がります。
### レビュー観点
- セキュリティ
- このPRをマージすることで、脆弱性を生まないか?
- パフォーマンス
- このPRをマージすることで、予期せずパフォーマンスが悪化しないか?
- もっと効率的な方法は無いか?
- テスト
- 期待する振る舞いがテストで担保されているか?
- 抜けやモレは無いか?
- 異常系のチェックは出来ているか?
The MIT License (MIT)
Copyright (c) 2020 Marihachi
Copyright (c) 2020-2022 Marihachi and other contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
......
# mfm.js
An MFM parser implementation with PEG.js.
[Try it out!](https://runkit.com/npm/mfm-js)
[![Test](https://github.com/misskey-dev/mfm.js/actions/workflows/test.yml/badge.svg)](https://github.com/misskey-dev/mfm.js/actions/workflows/test.yml)
[![codecov](https://codecov.io/gh/misskey-dev/mfm.js/branch/develop/graph/badge.svg?token=irAWFiHK8T)](https://codecov.io/gh/misskey-dev/mfm.js)
[![NPM](https://nodei.co/npm/mfm-js.png?downloads=true&downloadRank=true&stars=true)](https://www.npmjs.com/package/mfm-js)
# sfm.js
An SFM parser implementation with fixes based on MFM
## Installation
```
npm i mfm-js
npm config set @transfem-org:registry https://activitypub.software/api/v4/packages/npm/
npm i @transfem-org/sfm-js
```
## Usage
......@@ -17,7 +12,7 @@ Please see [docs](./docs/index.md) for the detail.
TypeScript:
```ts
import * as mfm from 'mfm-js';
import * as mfm from '@transfem-org/sfm-js';
const inputText =
`<center>
......@@ -28,11 +23,11 @@ I'm @ai, A bot of misskey!
https://github.com/syuilo/ai
</center>`;
// Generate a MFM tree from the MFM text.
// Generate a MFM tree from the full MFM text.
const mfmTree = mfm.parse(inputText);
// Generate a MFM tree from the MFM plain text.
const plainMfmTree = mfm.parsePlain('I like the hot soup :soup:​');
// Generate a MFM tree from the simple MFM text.
const simpleMfmTree = mfm.parseSimple('I like the hot soup :soup:​');
// Reverse to a MFM text from the MFM tree.
const text = mfm.toString(mfmTree);
......@@ -42,12 +37,12 @@ const text = mfm.toString(mfmTree);
## Develop
### 1. Clone
```
git clone https://github.com/misskey-dev/mfm.js.git
git clone https://activitypub.software/TransFem-org/sfm-js.git
```
### 2. Install packages
```
cd mfm.js
cd sfm.js
npm i
```
......@@ -62,9 +57,9 @@ full parser:
npm run parse
```
plain parser:
simple parser:
```
npm run parse-plain
npm run parse-simple
```
## License
......
# Contribution guide
:v: Thanks for your contributions :v:
**ℹ️ Important:** This project uses Japanese as its major language, **but you do not need to translate and write the Issues/PRs in Japanese.**
Also, you might receive comments on your Issue/PR in Japanese, but you do not need to reply to them in Japanese as well.\
The accuracy of translation into Japanese is not high, so it will be easier for us to understand if you write it in the original language.
It will also allow the reader to use the translation tool of their preference if necessary.
## Issues
Before creating an issue, please check the following:
- To avoid duplication, please search for similar issues before creating a new issue.
- Do not use Issues as a question.
- Issues should only be used to feature requests, suggestions, and report problems.
- Please ask questions in the [Misskey Forum](https://forum.misskey.io/) or [Discord](https://discord.gg/Wp8gVStHW3).
## Creating a PR
Thank you for your PR! Before creating a PR, please check the following:
- If possible, prefix the title with a keyword that identifies the type of this PR, as shown below.
- fix / refactor / feat / enhance / perf / chore etc.
- Also, make sure that the granularity of this PR is appropriate. Please do not include more than one type of change or interest in a single PR.
- If there is an Issue which will be resolved by this PR, please include a reference to the Issue in the text.
- Please add the summary of the changes to [`CHANGELOG.md`](/CHANGELOG.md). However, this is not necessary for changes that do not affect the users, such as refactoring.
- Check if there are any documents that need to be created or updated due to this change.
- If you have added a feature or fixed a bug, please add a test case if possible.
- Please make sure that tests and Lint are passed in advance.
- You can run it with `npm run test` and `npm run lint`.
- Run `npm run api` to update the API report and commit it if there are any diffs.
Thanks for your cooperation 🤗
## Testing with Sharkey
Let's say you have Sharkey checked out at `~/src/Sharkey`, and this
repository at `~/src/sfm-js`. You have made some modifications to this
code, and want to run Sharkey with your modifications.
```shell
cd ~/src/Sharkey
pnpm --filter=backend add ../../../sfm-js
pnpm --filter=frontend add ../../../sfm-js
```
this will replace the "real" `@transfem-org/sfm-js` in the
dependencies, with your local version. Remember to *not* commit the
changes to `package.json` that this causes! (`pnpm link` should also
work, but I couldn't figure it out)
Then you'll need to tell Vite to handle that package specially. Edit
`packages/frontend/vite.config.local-dev.ts` and add, before `define`:
```json
optimizeDeps: {
include: ['@transfem-org/sfm-js'],
},
```
Now you can `pnpm dev` and test your changes.
......@@ -4,20 +4,30 @@
例:
```ts
const nodes = mfm.parse('hello [tada world]');
const nodes = mfm.parse('hello $[tada world]');
console.log(JSON.stringify(nodes));
// => "[{"type":"text","props":{"text":"hello "}},{"type":"fn","props":{"name":"tada","args":{}},"children":[{"type":"text","props":{"text":"world"}}]}]"
// => [{"type":"text","props":{"text":"hello "}},{"type":"fn","props":{"name":"tada","args":{}},"children":[{"type":"text","props":{"text":"world"}}]}]
```
## parsePlain API
### 最大のネストの深さを変更する
デフォルトで20に設定されています。
例:
```ts
const nodes = mfm.parse('**<s>cannot nest</s>**', { nestLimit: 1 });
console.log(JSON.stringify(nodes));
// => [{"type":"bold","children":[{"type":"text","props":{"text":"<s>cannot nest</s>"}}]}]
```
## parseSimple API
入力文字列からノードツリーを生成します。
絵文字コードとUnicode絵文字を利用可能です。
例:
```ts
const nodes = mfm.parsePlain('Hello :surprised_ai:');
const nodes = mfm.parseSimple('Hello :surprised_ai:');
console.log(JSON.stringify(nodes));
// => "[{"type":"text","props":{"text":"Hello "}},{"type":"emojiCode","props":{"name":"surprised_ai"}}]"
// => [{"type":"text","props":{"text":"Hello "}},{"type":"emojiCode","props":{"name":"surprised_ai"}}]
```
## toString API
......@@ -25,9 +35,9 @@ console.log(JSON.stringify(nodes));
例:
```ts
const nodes = mfm.parse('hello [tada world]');
const nodes = mfm.parse('hello $[tada world]');
const output = mfm.toString(nodes);
console.log(output); // => "hello [tada world]"
console.log(output); // => "hello $[tada world]"
```
※元の文字列とtoString APIで出力される文字列の同一性は保障されません。
......
......@@ -8,27 +8,25 @@
- [中央寄せブロック](#center)
インライン構文:
構文 | 改行可能?
-------------------------------|-----------
[揺れる字](#big) | はい
[太字](#bold) | はい
[目立たない字](#small) | はい
[イタリック](#italic) | はい
[打ち消し線](#strike) | いいえ
[インラインコード](#inline-code) | いいえ
[インライン数式](#math-inline) | いいえ
[メンション](#mention) | いいえ
[ハッシュタグ](#hashtag) | いいえ
[URL](#url) | いいえ
[リンク](#link) | いいえ
[絵文字コード(カスタム絵文字)](#emoji-code) | いいえ
[MFM関数](#fn) | はい
[Unicode絵文字](#unicode-emoji) | いいえ
[テキスト](#text) | はい
<h1 id="quote">引用ブロック</h1>
- [揺れる字](#big)
- [太字](#bold)
- [目立たない字](#small)
- [イタリック](#italic)
- [打ち消し線](#strike)
- [インラインコード](#inline-code)
- [インライン数式](#math-inline)
- [メンション](#mention)
- [ハッシュタグ](#hashtag)
- [URL](#url)
- [リンク](#link)
- [絵文字コード(カスタム絵文字)](#emoji-code)
- [MFM関数](#fn)
- [Unicode絵文字](#unicode-emoji)
- [テキスト](#text)
<h1 id="quote">Block: 引用ブロック</h1>
## 形式
```
......@@ -37,6 +35,13 @@
>>nest
```
## 詳細
- 引用された内容には再度FullParserを適用する。
- `>`の後に続く0~1文字のスペースを無視する。
- 隣接する引用の行は一つになる。
- 複数行の引用では空行も含めることができる。
- 引用の後ろにある空行は無視される。([#61](https://github.com/misskey-dev/mfm.js/issues/61))
## ノード
```js
{
......@@ -47,17 +52,9 @@
}
```
## 詳細
- ブロック構文です。
- 引用された内容には再度FullParserを適用する。
- `>`の後に続く0~1文字のスペースを無視する。
- 隣接する引用の行は一つになる。
- 複数行の引用では空行も含めることができる。
- 引用の後ろにある空行は無視される。([#61](https://github.com/misskey-dev/mfm.js/issues/61))
<h1 id="search">検索ブロック</h2>
<h1 id="search">Block: 検索ブロック</h2>
## 形式
```
......@@ -67,6 +64,9 @@ MFM 書き方 [Search]
MFM 書き方 [検索]
```
## 詳細
- Searchの大文字小文字は区別されない。
## ノード
```js
{
......@@ -78,13 +78,9 @@ MFM 書き方 [検索]
}
```
## 詳細
- ブロック構文。
- Searchの大文字小文字は区別されない。
<h1 id="code-block">コードブロック</h2>
<h1 id="code-block">Block: コードブロック</h2>
## 形式
<pre>
......@@ -103,6 +99,9 @@ abc
````
</pre>
## 詳細
- langは指定されない場合はnullになる。
## ノード
```js
{
......@@ -114,13 +113,9 @@ abc
}
```
## 詳細
- ブロック構文です。
- langは指定されない場合はnullになる。
<h1 id="math-block">数式ブロック</h2>
<h1 id="math-block">Block: 数式ブロック</h2>
## 形式
```
......@@ -133,6 +128,11 @@ a = 2
\]
```
## 詳細
- `\[`は行頭でなければならない。
- `\]`は行末でなければならない。
- 前後のスペースと改行はトリミングされる。
## ノード
```js
{
......@@ -143,15 +143,9 @@ a = 2
}
```
## 詳細
- ブロック構文です。
- `\[`は行頭でなければならない。
- `\]`は行末でなければならない。
- 前後のスペースと改行はトリミングされる。
<h1 id="center">中央寄せブロック</h2>
<h1 id="center">Block: 中央寄せブロック</h2>
## 形式
```
......@@ -163,6 +157,11 @@ abc
</center>
```
## 詳細
- `<center>`は行頭でなければならない。
- `</center>`は行末でなければならない。
- 内容には再度InlineParserを適用する。
## ノード
```js
{
......@@ -173,16 +172,9 @@ abc
}
```
## 詳細
- ブロック構文。
- `<center>`は行頭でなければならない。
- `</center>`は行末でなければならない。
- 中身を空にすることはできない。
- 内容には再度InlineParserを適用する。
<h1 id="big">揺れる字</h2>
<h1 id="big">Inline: 揺れる字</h2>
**廃止予定の構文。代替の構文が用意されています。**
## 形式
......@@ -190,6 +182,11 @@ abc
***big!***
```
## 詳細
- 内容には再度InlineParserを適用する。
- 内容にはすべての文字、改行が使用できる。
- 内容を空にすることはできない。
## ノード
```js
{
......@@ -204,24 +201,36 @@ abc
}
```
## 詳細
- インライン構文
- 内容には再度InlineParserを適用する。
- 内容には改行も含めることが可能です。
<h1 id="bold">太字</h2>
<h1 id="bold">Inline: 太字</h2>
## 形式
構文1:
```
**bold**
```
構文2:
```
__bold__
```
構文3:
```
<b>bold</b>
```
## 詳細
- 内容には再度InlineParserを適用する。
- 内容を空にすることはできない。
構文1,3のみ:
- 内容にはすべての文字、改行が使用できる。
構文2のみ:
- 内容には`[a-z0-9 \t]i`にマッチする文字が使用できる。
## ノード
```js
{
......@@ -232,20 +241,20 @@ __bold__
}
```
## 詳細
- インライン構文。
- 内容には再度InlineParserを適用する。
- 内容には改行も含めることが可能です。
<h1 id="small">目立たない字</h2>
<h1 id="small">Inline: 目立たない字</h2>
## 形式
```
<small>small</small>
```
## 詳細
- 内容には再度InlineParserを適用する。
- 内容を空にすることはできない。
- 内容にはすべての文字、改行が使用できる。
## ノード
```js
{
......@@ -256,14 +265,9 @@ __bold__
}
```
## 詳細
- インライン構文です。
- 内容には再度InlineParserを適用する。
- 内容には改行も含めることが可能です。
<h1 id="italic">イタリック</h2>
<h1 id="italic">Inline: イタリック</h2>
## 形式
構文1:
......@@ -281,6 +285,18 @@ __bold__
_italic_
```
## 詳細
- 内容には再度InlineParserを適用する。
- 内容を空にすることはできない。
構文1のみ:
- 内容にはすべての文字、改行が使用できる。
構文2,3のみ:
※1つ目の`*``_`を開始記号と呼ぶ。
- 内容には`[a-z0-9 \t]i`にマッチする文字が使用できる。
- 開始記号の前の文字が`[a-z0-9]i`に一致しない時にイタリック文字として判定される。
## ノード
```js
{
......@@ -291,27 +307,31 @@ _italic_
}
```
## 詳細
- インライン構文。
- 内容には再度InlineParserを適用する。
構文1のみ:
- 内容には改行も含めることが可能です。
構文2,3のみ:
※1つ目の`*``_`を開始記号と呼ぶ。
- 内容には`[a-z0-9 \t]i`にマッチする文字が使用できる。
- 開始記号の前の文字が(無い、改行、半角スペース、[a-zA-Z0-9]に一致しない)のいずれかの時にイタリック文字として判定される。
<h1 id="strike">打ち消し線</h2>
<h1 id="strike">Inline: 打ち消し線</h2>
## 形式
構文1:
```
~~strike~~
```
構文2:
```
<s>strike</s>
```
## 詳細
- 内容には再度InlineParserを適用する。
- 内容を空にすることはできない。
構文1のみ:
- 内容には`~`、改行以外の文字を使用できる。
構文2のみ:
- 内容にはすべての文字、改行が使用できる。
## ノード
```js
{
......@@ -322,21 +342,20 @@ _italic_
}
```
## 詳細
- インライン構文。
- 内容には再度InlineParserを適用する。
- 内容には改行を含めることができない。
- 内容には`~`を含めることができない。
<h1 id="inline-code">インラインコード</h2>
<h1 id="inline-code">Inline: インラインコード</h2>
## 形式
```
`$abc <- 1`
```
## 詳細
- 内容を空にすることはできない。
- 内容には改行を含めることができない。
- 内容には「´」を含めることができない。
## ノード
```js
{
......@@ -347,20 +366,19 @@ _italic_
}
```
## 詳細
- インライン構文。
- 内容には改行を含めることができない。
- 内容には「´」を含めることができない。
<h1 id="math-inline">インライン数式</h2>
<h1 id="math-inline">Inline: インライン数式</h2>
## 形式
```
\(y = 2x\)
```
## 詳細
- 内容を空にすることはできない。
- 内容には改行を含めることができない。
## ノード
```js
{
......@@ -371,13 +389,9 @@ _italic_
}
```
## 詳細
- インライン構文。
- 内容には改行を含めることができない。
<h1 id="mention">メンション</h2>
<h1 id="mention">Inline: メンション</h2>
## 形式
```
......@@ -387,6 +401,19 @@ _italic_
@user
```
## 詳細
- 最初の`@`の前の文字が`[a-z0-9]i`に一致しない場合にメンションとして認識する。
### ユーザ名
- 1文字以上。
- `A``Z` `0``9` `_` `-`が含められる。
- 1文字目と最後の文字は`-`にできない。
### ホスト名
- 1文字以上。
- `A``Z` `0``9` `_` `-` `.`が含められる。
- 1文字目と最後の文字は`-` `.`にできない。
## ノード
```js
{
......@@ -410,29 +437,23 @@ _italic_
}
```
## 詳細
- インライン構文。
- 最初の`@`の前の文字が(改行、スペース、無し、[a-zA-Z0-9]に一致しない)のいずれかの場合にメンションとして認識する。
### ユーザ名
- 1文字以上。
- `A``Z` `0``9` `_` `-`が含められる。
- 1文字目と最後の文字は`-`にできない。
### ホスト名
- 1文字以上。
- `A``Z` `0``9` `_` `-` `.`が含められる。
- 1文字目と最後の文字は`-` `.`にできない。
<h1 id="hashtag">ハッシュタグ</h2>
<h1 id="hashtag">Inline: ハッシュタグ</h2>
## 形式
```
#abc
```
## 詳細
- 内容を空にすることはできない。
- 内容には半角スペース、全角スペース、改行、タブ文字を含めることができない。
- 内容には`.` `,` `!` `?` `'` `"` `#` `:` `/` `【` `】` `<` `>` `【` `】` `(` `)` `「` `」` `(` `)` を含めることができない。
- 括弧は対になっている時のみ内容に含めることができる。対象: `()` `[]` `「」` `()`
- `#`の前の文字が`[a-z0-9]i`に一致しない場合にハッシュタグとして認識する。
- 内容が数字のみの場合はハッシュタグとして認識しない。
## ノード
```js
{
......@@ -443,17 +464,9 @@ _italic_
}
```
## 詳細
- インライン構文。
- 内容には半角スペース、全角スペース、改行、タブ文字を含めることができない。
- 内容には`.` `,` `!` `?` `'` `"` `#` `:` `/` `【` `】` を含めることができない。
- 括弧は対になっている時のみ内容に含めることができる。対象: `()` `[]` `「」`
- `#`の前の文字が(改行、スペース、無し、[a-zA-Z0-9]に一致しない)のいずれかの場合にハッシュタグとして認識する。
- 内容が数字のみの場合はハッシュタグとして認識しない。
<h1 id="url">URL</h2>
<h1 id="url">Inline: URL</h2>
## 形式
構文1:
......@@ -474,6 +487,15 @@ http://hoge.jp/abc
<http://藍.jp/abc>
```
## 詳細
構文1のみ:
- 内容には`[.,a-z0-9_/:%#@$&?!~=+-]i`にマッチする文字を使用できる。
- 内容には対になっている括弧を使用できる。対象: `( )` `[ ]`
- `.``,`は最後の文字にできない。
構文2のみ:
- 内容には改行、スペース以外の文字を使用できる。
## ノード
構文1:
```js
......@@ -508,20 +530,9 @@ http://hoge.jp/abc
}
```
## 詳細
- インライン構文。
構文1のみ:
- 内容には`[.,a-z0-9_/:%#@$&?!~=+-]i`にマッチする文字を使用できる。
- 内容には対になっている括弧を使用できる。対象: `(` `)` `[` `]`
- `.``,`は最後の文字にできない。
構文2のみ:
- 内容には改行、スペース以外の文字を使用できる。
<h1 id="link">リンク</h2>
<h1 id="link">Inline: リンク</h2>
## 形式
silent=false
......@@ -534,6 +545,9 @@ silent=true
?[Misskey.io](https://misskey.io/)
```
## 詳細
- 表示テキストには再度InlineParserを適用する。ただし、表示テキストではURL、リンク、メンションは使用できない。
## ノード
```js
[
......@@ -555,20 +569,19 @@ silent=true
]
```
## 詳細
- インライン構文。
- リンクラベルには再度InlineParserを適用する。
- リンクラベルに含まれるURL、リンク、メンションはテキストとしてパースする。
<h1 id="emoji-code">絵文字コード(カスタム絵文字)</h2>
<h1 id="emoji-code">Inline: 絵文字コード(カスタム絵文字)</h2>
## 形式
```
:thinking_ai:
```
## 詳細
- 内容を空にすることはできない。
- 内容には[a-z0-9_+-]iにマッチする文字を使用できる。
## ノード
```js
{
......@@ -579,12 +592,9 @@ silent=true
}
```
## 詳細
- インライン構文。
<h1 id="fn">関数</h2>
<h1 id="fn">Inline: 関数</h2>
## 形式
構文1:
......@@ -604,23 +614,10 @@ $[shake.speed=1s 🍮]
$[flip.h,v MisskeyでFediverseの世界が広がります]
```
構文2:
**廃止予定の構文。代替の構文(構文1)が用意されています。**
```
[shake 🍮]
```
```
[spin.alternate 🍮]
```
```
[shake.speed=1s 🍮]
```
```
[flip.h,v MisskeyでFediverseの世界が広がります]
```
## 詳細
- 内容には再度InlineParserを適用する。
- 内容を空にすることはできない。
- 内容には改行も含めることが可能です。
## ノード
```js
......@@ -636,15 +633,9 @@ $[flip.h,v MisskeyでFediverseの世界が広がります]
}
```
## 詳細
- インライン構文
- 内容には再度InlineParserを適用する。
- 内容には改行も含めることが可能です。
- 使用できる関数名やパラメータはホスト側で定義され、パーサはその登録状況を関知しません。
<h1 id="unicode-emoji">Unicode絵文字</h2>
<h1 id="unicode-emoji">Inline: Unicode絵文字</h2>
## 形式
```
......@@ -663,7 +654,7 @@ $[flip.h,v MisskeyでFediverseの世界が広がります]
<h1 id="text">テキスト</h2>
<h1 id="text">Inline: テキスト</h2>
## 形式
```
......
......@@ -105,7 +105,7 @@ export type MfmHashtag = {
};
// @public (undocumented)
export type MfmInline = MfmUnicodeEmoji | MfmEmojiCode | MfmBold | MfmSmall | MfmItalic | MfmStrike | MfmInlineCode | MfmMathInline | MfmMention | MfmHashtag | MfmUrl | MfmLink | MfmFn | MfmText;
export type MfmInline = MfmUnicodeEmoji | MfmEmojiCode | MfmBold | MfmSmall | MfmItalic | MfmStrike | MfmInlineCode | MfmMathInline | MfmMention | MfmHashtag | MfmUrl | MfmLink | MfmFn | MfmPlain | MfmText;
// @public (undocumented)
export type MfmInlineCode = {
......@@ -165,6 +165,13 @@ export type MfmMention = {
// @public (undocumented)
export type MfmNode = MfmBlock | MfmInline;
// @public (undocumented)
export type MfmPlain = {
type: 'plain';
props?: Record<string, unknown>;
children: MfmText[];
};
// @public (undocumented)
export type MfmQuote = {
type: 'quote';
......@@ -182,6 +189,9 @@ export type MfmSearch = {
children?: [];
};
// @public (undocumented)
export type MfmSimpleNode = MfmUnicodeEmoji | MfmEmojiCode | MfmText | MfmPlain;
// @public (undocumented)
export type MfmSmall = {
type: 'small';
......@@ -225,18 +235,21 @@ export type MfmUrl = {
};
// @public (undocumented)
export const N_URL: (value: string, brackets?: boolean | undefined) => NodeType<'url'>;
export const N_URL: (value: string, brackets?: boolean) => NodeType<'url'>;
// @public (undocumented)
export type NodeType<T extends MfmNode['type']> = T extends 'quote' ? MfmQuote : T extends 'search' ? MfmSearch : T extends 'blockCode' ? MfmCodeBlock : T extends 'mathBlock' ? MfmMathBlock : T extends 'center' ? MfmCenter : T extends 'unicodeEmoji' ? MfmUnicodeEmoji : T extends 'emojiCode' ? MfmEmojiCode : T extends 'bold' ? MfmBold : T extends 'small' ? MfmSmall : T extends 'italic' ? MfmItalic : T extends 'strike' ? MfmStrike : T extends 'inlineCode' ? MfmInlineCode : T extends 'mathInline' ? MfmMathInline : T extends 'mention' ? MfmMention : T extends 'hashtag' ? MfmHashtag : T extends 'url' ? MfmUrl : T extends 'link' ? MfmLink : T extends 'fn' ? MfmFn : T extends 'plain' ? MfmPlain : T extends 'text' ? MfmText : never;
// @public (undocumented)
export type NodeType<T extends MfmNode['type']> = T extends 'quote' ? MfmQuote : T extends 'search' ? MfmSearch : T extends 'blockCode' ? MfmCodeBlock : T extends 'mathBlock' ? MfmMathBlock : T extends 'center' ? MfmCenter : T extends 'unicodeEmoji' ? MfmUnicodeEmoji : T extends 'emojiCode' ? MfmEmojiCode : T extends 'bold' ? MfmBold : T extends 'small' ? MfmSmall : T extends 'italic' ? MfmItalic : T extends 'strike' ? MfmStrike : T extends 'inlineCode' ? MfmInlineCode : T extends 'mathInline' ? MfmMathInline : T extends 'mention' ? MfmMention : T extends 'hashtag' ? MfmHashtag : T extends 'url' ? MfmUrl : T extends 'link' ? MfmLink : T extends 'fn' ? MfmFn : T extends 'text' ? MfmText : never;
export function parse(input: string, opts?: Partial<{
nestLimit: number;
}>): MfmNode[];
// @public (undocumented)
export function parse(input: string): MfmNode[];
export function parseSimple(input: string): MfmSimpleNode[];
// Warning: (ae-forgotten-export) The symbol "MfmPlainNode" needs to be exported by the entry point index.d.ts
//
// @public (undocumented)
export function parsePlain(input: string): MfmPlainNode[];
export const PLAIN: (text: string) => NodeType<'plain'>;
// @public (undocumented)
export const QUOTE: (children: MfmNode[]) => NodeType<'quote'>;
......
This diff is collapsed.
{
"name": "mfm-js",
"version": "0.19.0",
"description": "An MFM parser implementation with PEG.js",
"name": "@transfem-org/sfm-js",
"version": "0.24.4",
"description": "An SFM parser implementation with fixes based on MFM",
"main": "./built/index.js",
"types": "./built/index.d.ts",
"scripts": {
"build": "npm run tsc && npm run peg",
"build-debug": "npm run tsc && npm run peg-debug",
"peg": "peggy --cache -o src/internal/parser.js --allowed-start-rules fullParser,inlineParser,plainParser src/internal/parser.pegjs && npm run peg-copy",
"peg-debug": "peggy --cache -o src/internal/parser.js --allowed-start-rules fullParser,inlineParser,plainParser --trace src/internal/parser.pegjs && npm run peg-copy",
"peg-copy": "copyfiles -f src/internal/parser.js built/internal/",
"build": "npm run tsc",
"tsc": "tsc",
"tsd": "tsd",
"parse": "node ./built/cli/parse",
"parse-plain": "node ./built/cli/parsePlain",
"parse-simple": "node ./built/cli/parseSimple",
"api": "npx api-extractor run --local --verbose",
"api-prod": "npx api-extractor run --verbose",
"lint": "eslint . --ext .js,.jsx,.ts,.tsx",
......@@ -22,29 +18,29 @@
},
"repository": {
"type": "git",
"url": "git+https://github.com/misskey-dev/mfm.js.git"
"url": "git+https://activitypub.software/TransFem-org/sfm.js.git"
},
"author": "Marihachi",
"author": "Marie",
"license": "MIT",
"devDependencies": {
"@microsoft/api-extractor": "^7.18.4",
"@types/jest": "^26.0.23",
"@types/node": "15.12.4",
"@typescript-eslint/eslint-plugin": "^4.28.5",
"@typescript-eslint/parser": "^4.28.5",
"copyfiles": "^2.4.1",
"eslint": "^7.32.0",
"jest": "^27.0.5",
"peggy": "1.2.0",
"ts-jest": "^27.0.3",
"ts-node": "10.0.0",
"tsd": "^0.17.0",
"typescript": "4.3.4"
"@microsoft/api-extractor": "7.38.5",
"@types/jest": "29.5.11",
"@types/node": "20.10.5",
"@typescript-eslint/eslint-plugin": "6.14.0",
"@typescript-eslint/parser": "6.14.0",
"eslint": "8.56.0",
"jest": "29.7.0",
"ts-jest": "29.1.1",
"ts-node": "10.9.2",
"tsd": "0.30.0",
"tslib": "2.6.2",
"typescript": "5.3.3"
},
"dependencies": {
"twemoji-parser": "13.1.x"
"@twemoji/parser": "15.0.0"
},
"files": [
"built"
"built",
"CHANGELOG.md"
]
}
declare module '@twemoji/parser/dist/lib/regex' {
const regex: RegExp;
export default regex;
}