Got ffm.js working

This commit is contained in:
Sal Rahman 2023-08-14 04:25:38 -07:00
parent 814bdc4eb8
commit 1880995e06
29 changed files with 41 additions and 32 deletions

View file

@ -1,5 +1,6 @@
import { JSDOM } from "jsdom"; import { JSDOM } from "jsdom";
import type * as mfm from "mfm-js"; // import type * as mfm from "mfm-js";
import type * as mfm from "ffm-js";
import config from "@/config/index.js"; import config from "@/config/index.js";
import { intersperse } from "@/prelude/array.js"; import { intersperse } from "@/prelude/array.js";
import type { IMentionedRemoteUsers } from "@/models/entities/note.js"; import type { IMentionedRemoteUsers } from "@/models/entities/note.js";

View file

@ -1,4 +1,4 @@
import * as mfm from "mfm-js"; import * as mfm from "ffm-js";
import { unique } from "@/prelude/array.js"; import { unique } from "@/prelude/array.js";
export function extractCustomEmojisFromMfm(nodes: mfm.MfmNode[]): string[] { export function extractCustomEmojisFromMfm(nodes: mfm.MfmNode[]): string[] {

View file

@ -1,4 +1,4 @@
import * as mfm from "mfm-js"; import * as mfm from "ffm-js";
import { unique } from "@/prelude/array.js"; import { unique } from "@/prelude/array.js";
export function extractHashtags(nodes: mfm.MfmNode[]): string[] { export function extractHashtags(nodes: mfm.MfmNode[]): string[] {

View file

@ -1,6 +1,6 @@
// test is located in test/extract-mentions // test is located in test/extract-mentions
import * as mfm from "mfm-js"; import * as mfm from "ffm-js";
export function extractMentions( export function extractMentions(
nodes: mfm.MfmNode[], nodes: mfm.MfmNode[],

View file

@ -1,5 +1,5 @@
import { In } from "typeorm"; import { In } from "typeorm";
import * as mfm from "mfm-js"; import * as mfm from "ffm-js";
import { Note } from "@/models/entities/note.js"; import { Note } from "@/models/entities/note.js";
import type { User } from "@/models/entities/user.js"; import type { User } from "@/models/entities/user.js";
import { import {

View file

@ -1,4 +1,4 @@
import * as mfm from "mfm-js"; import * as mfm from "ffm-js";
import type { Note } from "@/models/entities/note.js"; import type { Note } from "@/models/entities/note.js";
import { toHtml } from "../../../mfm/to-html.js"; import { toHtml } from "../../../mfm/to-html.js";

View file

@ -1,5 +1,5 @@
import promiseLimit from "promise-limit"; import promiseLimit from "promise-limit";
import * as mfm from "mfm-js"; import * as mfm from "ffm-js";
import config from "@/config/index.js"; import config from "@/config/index.js";
import Resolver from "../resolver.js"; import Resolver from "../resolver.js";
import post from "@/services/note/create.js"; import post from "@/services/note/create.js";

View file

@ -1,5 +1,5 @@
import { URL } from "node:url"; import { URL } from "node:url";
import * as mfm from "mfm-js"; import * as mfm from "ffm-js";
import config from "@/config/index.js"; import config from "@/config/index.js";
import type { ILocalUser } from "@/models/entities/user.js"; import type { ILocalUser } from "@/models/entities/user.js";
import { DriveFiles, UserProfiles } from "@/models/index.js"; import { DriveFiles, UserProfiles } from "@/models/index.js";

View file

@ -1,5 +1,5 @@
import RE2 from "re2"; import RE2 from "re2";
import * as mfm from "mfm-js"; import * as mfm from "ffm-js";
import { publishMainStream, publishUserEvent } from "@/services/stream.js"; import { publishMainStream, publishUserEvent } from "@/services/stream.js";
import acceptAllFollowRequests from "@/services/following/requests/accept-all.js"; import acceptAllFollowRequests from "@/services/following/requests/accept-all.js";
import { publishToFollowers } from "@/services/i/update.js"; import { publishToFollowers } from "@/services/i/update.js";

View file

@ -21,7 +21,7 @@ import define from "../../define.js";
import { HOUR } from "@/const.js"; import { HOUR } from "@/const.js";
import { getNote } from "../../common/getters.js"; import { getNote } from "../../common/getters.js";
import { Poll } from "@/models/entities/poll.js"; import { Poll } from "@/models/entities/poll.js";
import * as mfm from "mfm-js"; import * as mfm from "ffm-js";
import { concat } from "@/prelude/array.js"; import { concat } from "@/prelude/array.js";
import { extractHashtags } from "@/misc/extract-hashtags.js"; import { extractHashtags } from "@/misc/extract-hashtags.js";
import { extractCustomEmojisFromMfm } from "@/misc/extract-custom-emojis-from-mfm.js"; import { extractCustomEmojisFromMfm } from "@/misc/extract-custom-emojis-from-mfm.js";

View file

@ -1,4 +1,4 @@
import * as mfm from "mfm-js"; import * as mfm from "ffm-js";
import es from "../../db/elasticsearch.js"; import es from "../../db/elasticsearch.js";
import sonic from "../../db/sonic.js"; import sonic from "../../db/sonic.js";
import { import {

View file

@ -1,6 +1,6 @@
import * as assert from "assert"; import * as assert from "assert";
import { parse } from "mfm-js"; import { parse } from "ffm-js";
import { extractMentions } from "../src/misc/extract-mentions.js"; import { extractMentions } from "../src/misc/extract-mentions.js";
describe("Extract mentions", () => { describe("Extract mentions", () => {

View file

@ -1,5 +1,5 @@
import * as assert from "assert"; import * as assert from "assert";
import * as mfm from "mfm-js"; import * as mfm from "ffm-js";
import { toHtml } from "../src/mfm/to-html.js"; import { toHtml } from "../src/mfm/to-html.js";
import { fromHtml } from "../src/mfm/from-html.js"; import { fromHtml } from "../src/mfm/from-html.js";

View file

@ -256,7 +256,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import { computed, inject, onMounted, ref } from "vue"; import { computed, inject, onMounted, ref } from "vue";
import * as mfm from "mfm-js"; import * as mfm from "ffm-js";
import type { Ref } from "vue"; import type { Ref } from "vue";
import type * as misskey from "firefish-js"; import type * as misskey from "firefish-js";
import MkNoteSub from "@/components/MkNoteSub.vue"; import MkNoteSub from "@/components/MkNoteSub.vue";

View file

@ -242,7 +242,7 @@ import {
ref, ref,
computed, computed,
} from "vue"; } from "vue";
import * as mfm from "mfm-js"; import * as mfm from "ffm-js";
import * as misskey from "firefish-js"; import * as misskey from "firefish-js";
import autosize from "autosize"; import autosize from "autosize";
import insertTextAtCursor from "insert-text-at-cursor"; import insertTextAtCursor from "insert-text-at-cursor";

View file

@ -178,7 +178,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import { ref } from "vue"; import { ref } from "vue";
import * as misskey from "firefish-js"; import * as misskey from "firefish-js";
import * as mfm from "mfm-js"; import * as mfm from "ffm-js";
import * as os from "@/os"; import * as os from "@/os";
import XNoteSimple from "@/components/MkNoteSimple.vue"; import XNoteSimple from "@/components/MkNoteSimple.vue";
import XMediaList from "@/components/MkMediaList.vue"; import XMediaList from "@/components/MkMediaList.vue";

View file

@ -135,7 +135,7 @@ const embedId = `embed${Math.random().toString().replace(/\D/, "")}`;
let tweetHeight = ref(150); let tweetHeight = ref(150);
const requestUrl = new URL(props.url); const requestUrl = new URL(props.url);
if (!["http:", "https:"].includes(requestUrl.protocol)) if (!["http:", "https:", "gopher:", "gemini:", "matrix:"].includes(requestUrl.protocol))
throw new Error("invalid url"); throw new Error("invalid url");
if ( if (

View file

@ -11,14 +11,14 @@
@click.stop @click.stop
> >
<template v-if="!self"> <template v-if="!self">
<span class="schema">{{ schema }}//</span> <span class="schema">{{ schema }}{{ hostname.trim() != '' ? '//' : '' }}</span>
<span class="hostname">{{ hostname }}</span> <span class="hostname">{{ hostname.trim() != '' ? hostname.trim() : pathname }}</span>
<span v-if="port != ''" class="port">:{{ port }}</span> <span v-if="port != ''" class="port">:{{ port }}</span>
</template> </template>
<template v-if="pathname === '/' && self"> <template v-if="pathname === '/' && self">
<span class="self">{{ hostname }}</span> <span class="self">{{ hostname }}</span>
</template> </template>
<span v-if="pathname != ''" class="pathname">{{ <span v-if="pathname != '' && !!hostname" class="pathname">{{
self ? pathname.substring(1) : pathname self ? pathname.substring(1) : pathname
}}</span> }}</span>
<span class="query">{{ query }}</span> <span class="query">{{ query }}</span>
@ -45,7 +45,7 @@ const props = defineProps<{
const self = props.url.startsWith(local); const self = props.url.startsWith(local);
const url = new URL(props.url); const url = new URL(props.url);
if (!["http:", "https:"].includes(url.protocol)) throw new Error("invalid url"); if (!["http:", "https:", "gopher:", "gemini:", "matrix:"].includes(url.protocol)) throw new Error("invalid url");
const el = ref(); const el = ref();
useTooltip(el, (showing) => { useTooltip(el, (showing) => {

View file

@ -1,5 +1,5 @@
import { defineComponent, h } from "vue"; import { defineComponent, h } from "vue";
import * as mfm from "mfm-js"; import * as mfm from "ffm-js";
import type { VNode } from "vue"; import type { VNode } from "vue";
import MkUrl from "@/components/global/MkUrl.vue"; import MkUrl from "@/components/global/MkUrl.vue";
import MkLink from "@/components/MkLink.vue"; import MkLink from "@/components/MkLink.vue";

View file

@ -9,7 +9,7 @@
import { TextBlock } from "@/scripts/hpml/block"; import { TextBlock } from "@/scripts/hpml/block";
import { Hpml } from "@/scripts/hpml/evaluator"; import { Hpml } from "@/scripts/hpml/evaluator";
import { defineAsyncComponent, defineComponent, PropType } from "vue"; import { defineAsyncComponent, defineComponent, PropType } from "vue";
import * as mfm from "mfm-js"; import * as mfm from "ffm-js";
import { extractUrlFromMfm } from "@/scripts/extract-url-from-mfm"; import { extractUrlFromMfm } from "@/scripts/extract-url-from-mfm";
export default defineComponent({ export default defineComponent({
components: { components: {

View file

@ -85,7 +85,7 @@
import { computed } from "vue"; import { computed } from "vue";
import {} from "vue"; import {} from "vue";
import * as mfm from "mfm-js"; import * as mfm from "ffm-js";
import type * as Misskey from "firefish-js"; import type * as Misskey from "firefish-js";
import XMediaList from "@/components/MkMediaList.vue"; import XMediaList from "@/components/MkMediaList.vue";
import { extractUrlFromMfm } from "@/scripts/extract-url-from-mfm"; import { extractUrlFromMfm } from "@/scripts/extract-url-from-mfm";

View file

@ -1,6 +1,6 @@
// test is located in test/extract-mentions // test is located in test/extract-mentions
import * as mfm from "mfm-js"; import * as mfm from "ffm-js";
export function extractMentions( export function extractMentions(
nodes: mfm.MfmNode[], nodes: mfm.MfmNode[],

View file

@ -1,4 +1,4 @@
import * as mfm from "mfm-js"; import * as mfm from "ffm-js";
const animatedMfm = [ const animatedMfm = [
"tada", "tada",

View file

@ -1,4 +1,4 @@
import * as mfm from "mfm-js"; import * as mfm from "ffm-js";
import { unique } from "@/scripts/array"; import { unique } from "@/scripts/array";
// unique without hash // unique without hash

View file

@ -1,4 +1,4 @@
import * as mfm from "mfm-js"; import * as mfm from "ffm-js";
import { defaultStore } from "@/store"; import { defaultStore } from "@/store";
import { expandKaTeXMacro } from "@/scripts/katex-macro"; import { expandKaTeXMacro } from "@/scripts/katex-macro";

View file

@ -89,7 +89,7 @@ export default defineConfig(({ command, mode }) => {
sourcemap: process.env.NODE_ENV === "development", sourcemap: process.env.NODE_ENV === "development",
reportCompressedSize: false, reportCompressedSize: false,
commonjsOptions: { commonjsOptions: {
include: [/firefish-js/, /node_modules/], include: [/firefish-js/, /ffm-js/, /node_modules/],
}, },
}, },
optimizeDeps: { optimizeDeps: {

View file

@ -1,7 +1,7 @@
{ {
"name": "ffm-js", "name": "ffm-js",
"version": "0.23.3", "version": "0.23.3",
"description": "An MFM parser implementation with TypeScript", "description": "An FFM parser implementation with TypeScript",
"main": "./built/index.js", "main": "./built/index.js",
"types": "./built/index.d.ts", "types": "./built/index.d.ts",
"scripts": { "scripts": {

View file

@ -674,7 +674,7 @@ export const language = P.createLanguage({
])); ]));
const parser = P.seq([ const parser = P.seq([
notLinkLabel, notLinkLabel,
P.regexp(/https?:\/\//), P.regexp(/((https?)|(gemini)|(gopher)|(matrix)):\/\//),
innerItem.many(1).text(), innerItem.many(1).text(),
]); ]);
return new P.Parser<M.MfmUrl | string>((input, index, state) => { return new P.Parser<M.MfmUrl | string>((input, index, state) => {
@ -706,7 +706,7 @@ export const language = P.createLanguage({
const parser = P.seq([ const parser = P.seq([
notLinkLabel, notLinkLabel,
open, open,
P.regexp(/https?:\/\//), P.regexp(/((https?)|(gemini)|(gopher)|(matrix)):\/\//),
P.seq([P.notMatch(P.alt([close, space])), P.char], 1).many(1), P.seq([P.notMatch(P.alt([close, space])), P.char], 1).many(1),
close, close,
]).text(); ]).text();

View file

@ -912,6 +912,14 @@ hoge`;
assert.deepStrictEqual(mfm.parse(input), output); assert.deepStrictEqual(mfm.parse(input), output);
}); });
test('gopher', () => {
const input = 'gopher://misskey.io/@ai';
const output = [
N_URL('gopher://misskey.io/@ai'),
];
assert.deepStrictEqual(mfm.parse(input), output);
});
test('with other texts', () => { test('with other texts', () => {
const input = 'official instance: https://misskey.io/@ai.'; const input = 'official instance: https://misskey.io/@ai.';
const output = [ const output = [