Viewport indices extend beyond visible area

The viewport function returns the visible indices, but seems to return far beyond what is visible in the editor. I filled an editor (with line wrapping) with 30k characters, and viewport reported that all 30k were in view, while in reality, only ~1500 were.

If I add some line breaks, it gets more accurate.

Is it possible to get the “true” number of visible characters on the screen?

The viewport only starts and ends on line boundaries, so enormously long lines will be either entirely inside or entirely outside it. To avoid having to redraw on every pixel scrolled, an intentional margin beyond the actually visible content is drawn.

That’s what I expected. The issue is that very large lines are quite common for me, so I will have to place a workaround to try to avoid this. Do you think it’s possible for codemirror to report back the actual visible characters on the screen, or is this too costly?

Thank you.

The visibleRanges property gives you the actually rendered ranges (which will not include all of very long lines), and though it’s not the same as the stuff the user can actually see, it is going to be a lot less than the entire viewport when there are long lines, and might be the solution you’re looking for.

Thank you.

I’ve been experimenting a bit, and so far this seems like the most accurate solution. This works well with large documents when line wrapping is enabled, and reasonably well when line wrapping is not enabled.

I’m not sure of how performant it is though, do you have any advice?

const getVisibleIndex = cmInstance => {
  const { left, right, top, bottom } = cmInstance.getBoundingClientRect();

  const firstVisibleIndexFromLeft = cmInstance.posAtCoords({ x: left, y: top });
  const firstVisibleIndexFromRight = cmInstance.posAtCoords({ x: right, y: top });
  const lastVisibleIndexFromLeft = cmInstance.posAtCoords({ x: left, y: bottom });
  const lastVisibleIndexFromRight = cmInstance.posAtCoords({ x: right, y: bottom });

  const { from, to } = cmInstance.visibleRanges[0];

  return {
    firstVisibleIndex: Math.max(from, Math.min(firstVisibleIndexFromLeft, firstVisibleIndexFromRight)),
    lastVisibleIndex: Math.min(to, Math.max(lastVisibleIndexFromLeft, lastVisibleIndexFromRight)),
  };
};